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"
31 /* Link State Memory allocation */
32 DEFINE_MTYPE_STATIC(LIB
, LS_DB
, "Link State Database");
35 * Link State Node management functions
37 int ls_node_id_same(struct ls_node_id i1
, struct ls_node_id i2
)
39 if (i1
.origin
!= i2
.origin
)
42 if (i1
.origin
== UNKNOWN
)
45 if (i1
.origin
== ISIS_L1
|| i1
.origin
== ISIS_L2
) {
46 if (memcmp(i1
.id
.iso
.sys_id
, i2
.id
.iso
.sys_id
, ISO_SYS_ID_LEN
)
48 || (i1
.id
.iso
.level
!= i2
.id
.iso
.level
))
51 if (!IPV4_ADDR_SAME(&i1
.id
.ip
.addr
, &i2
.id
.ip
.addr
)
52 || !IPV4_ADDR_SAME(&i1
.id
.ip
.area_id
, &i2
.id
.ip
.area_id
))
59 struct ls_node
*ls_node_new(struct ls_node_id adv
, struct in_addr rid
,
64 if (adv
.origin
== UNKNOWN
)
67 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
69 if (!IPV4_NET0(rid
.s_addr
)) {
71 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID
);
73 if (adv
.origin
== OSPFv2
|| adv
.origin
== STATIC
74 || adv
.origin
== DIRECT
) {
75 new->router_id
= adv
.id
.ip
.addr
;
76 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID
);
79 if (!IN6_IS_ADDR_UNSPECIFIED(&rid6
)) {
80 new->router_id6
= rid6
;
81 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID6
);
86 void ls_node_del(struct ls_node
*node
)
91 XFREE(MTYPE_LS_DB
, node
);
94 int ls_node_same(struct ls_node
*n1
, struct ls_node
*n2
)
96 /* First, check pointer */
97 if ((n1
&& !n2
) || (!n1
&& n2
))
103 /* Then, verify Flags and Origin */
104 if (n1
->flags
!= n2
->flags
)
107 if (!ls_node_id_same(n1
->adv
, n2
->adv
))
110 /* Finally, check each individual parameters that are valid */
111 if (CHECK_FLAG(n1
->flags
, LS_NODE_NAME
)
112 && (strncmp(n1
->name
, n2
->name
, MAX_NAME_LENGTH
) != 0))
114 if (CHECK_FLAG(n1
->flags
, LS_NODE_ROUTER_ID
)
115 && !IPV4_ADDR_SAME(&n1
->router_id
, &n2
->router_id
))
117 if (CHECK_FLAG(n1
->flags
, LS_NODE_ROUTER_ID6
)
118 && !IPV6_ADDR_SAME(&n1
->router_id6
, &n2
->router_id6
))
120 if (CHECK_FLAG(n1
->flags
, LS_NODE_FLAG
)
121 && (n1
->node_flag
!= n2
->node_flag
))
123 if (CHECK_FLAG(n1
->flags
, LS_NODE_TYPE
) && (n1
->type
!= n2
->type
))
125 if (CHECK_FLAG(n1
->flags
, LS_NODE_AS_NUMBER
)
126 && (n1
->as_number
!= n2
->as_number
))
128 if (CHECK_FLAG(n1
->flags
, LS_NODE_SR
)) {
129 if (n1
->srgb
.flag
!= n2
->srgb
.flag
130 || n1
->srgb
.lower_bound
!= n2
->srgb
.lower_bound
131 || n1
->srgb
.range_size
!= n2
->srgb
.range_size
)
133 if ((n1
->algo
[0] != n2
->algo
[0])
134 || (n1
->algo
[1] != n2
->algo
[1]))
136 if (CHECK_FLAG(n1
->flags
, LS_NODE_SRLB
)
137 && ((n1
->srlb
.lower_bound
!= n2
->srlb
.lower_bound
138 || n1
->srlb
.range_size
!= n2
->srlb
.range_size
)))
140 if (CHECK_FLAG(n1
->flags
, LS_NODE_MSD
) && (n1
->msd
!= n2
->msd
))
144 /* OK, n1 & n2 are equal */
149 * Link State Attributes management functions
151 struct ls_attributes
*ls_attributes_new(struct ls_node_id adv
,
152 struct in_addr local
,
153 struct in6_addr local6
,
156 struct ls_attributes
*new;
158 if (adv
.origin
== UNKNOWN
)
161 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
163 if (!IPV4_NET0(local
.s_addr
)) {
164 new->standard
.local
= local
;
165 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
);
167 if (!IN6_IS_ADDR_UNSPECIFIED(&local6
)) {
168 new->standard
.local6
= local6
;
169 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR6
);
172 new->standard
.local_id
= local_id
;
173 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ID
);
176 /* Check that almost one identifier is set */
177 if (!CHECK_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
| LS_ATTR_LOCAL_ADDR6
178 | LS_ATTR_LOCAL_ID
)) {
179 XFREE(MTYPE_LS_DB
, new);
183 admin_group_init(&new->ext_admin_group
);
188 void ls_attributes_srlg_del(struct ls_attributes
*attr
)
194 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
198 UNSET_FLAG(attr
->flags
, LS_ATTR_SRLG
);
201 void ls_attributes_del(struct ls_attributes
*attr
)
206 ls_attributes_srlg_del(attr
);
208 admin_group_term(&attr
->ext_admin_group
);
210 XFREE(MTYPE_LS_DB
, attr
);
213 int ls_attributes_same(struct ls_attributes
*l1
, struct ls_attributes
*l2
)
215 /* First, check pointer */
216 if ((l1
&& !l2
) || (!l1
&& l2
))
222 /* Then, verify Flags and Origin */
223 if (l1
->flags
!= l2
->flags
)
226 if (!ls_node_id_same(l1
->adv
, l2
->adv
))
229 /* Finally, check each individual parameters that are valid */
230 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NAME
)
231 && strncmp(l1
->name
, l2
->name
, MAX_NAME_LENGTH
) != 0)
233 if (CHECK_FLAG(l1
->flags
, LS_ATTR_METRIC
) && (l1
->metric
!= l2
->metric
))
235 if (CHECK_FLAG(l1
->flags
, LS_ATTR_TE_METRIC
)
236 && (l1
->standard
.te_metric
!= l2
->standard
.te_metric
))
238 if (CHECK_FLAG(l1
->flags
, LS_ATTR_ADM_GRP
)
239 && (l1
->standard
.admin_group
!= l2
->standard
.admin_group
))
241 if (CHECK_FLAG(l1
->flags
, LS_ATTR_EXT_ADM_GRP
) &&
242 !admin_group_cmp(&l1
->ext_admin_group
, &l2
->ext_admin_group
))
244 if (CHECK_FLAG(l1
->flags
, LS_ATTR_LOCAL_ADDR
)
245 && !IPV4_ADDR_SAME(&l1
->standard
.local
, &l2
->standard
.local
))
247 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NEIGH_ADDR
)
248 && !IPV4_ADDR_SAME(&l1
->standard
.remote
, &l2
->standard
.remote
))
250 if (CHECK_FLAG(l1
->flags
, LS_ATTR_LOCAL_ADDR6
)
251 && !IPV6_ADDR_SAME(&l1
->standard
.local6
, &l2
->standard
.local6
))
253 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NEIGH_ADDR6
)
254 && !IPV6_ADDR_SAME(&l1
->standard
.remote6
, &l2
->standard
.remote6
))
256 if (CHECK_FLAG(l1
->flags
, LS_ATTR_LOCAL_ID
)
257 && (l1
->standard
.local_id
!= l2
->standard
.local_id
))
259 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NEIGH_ID
)
260 && (l1
->standard
.remote_id
!= l2
->standard
.remote_id
))
262 if (CHECK_FLAG(l1
->flags
, LS_ATTR_MAX_BW
)
263 && (l1
->standard
.max_bw
!= l2
->standard
.max_bw
))
265 if (CHECK_FLAG(l1
->flags
, LS_ATTR_MAX_RSV_BW
)
266 && (l1
->standard
.max_rsv_bw
!= l2
->standard
.max_rsv_bw
))
268 if (CHECK_FLAG(l1
->flags
, LS_ATTR_UNRSV_BW
)
269 && memcmp(&l1
->standard
.unrsv_bw
, &l2
->standard
.unrsv_bw
, 32) != 0)
271 if (CHECK_FLAG(l1
->flags
, LS_ATTR_REMOTE_AS
)
272 && (l1
->standard
.remote_as
!= l2
->standard
.remote_as
))
274 if (CHECK_FLAG(l1
->flags
, LS_ATTR_REMOTE_ADDR
)
275 && !IPV4_ADDR_SAME(&l1
->standard
.remote_addr
,
276 &l2
->standard
.remote_addr
))
278 if (CHECK_FLAG(l1
->flags
, LS_ATTR_REMOTE_ADDR6
)
279 && !IPV6_ADDR_SAME(&l1
->standard
.remote_addr6
,
280 &l2
->standard
.remote_addr6
))
282 if (CHECK_FLAG(l1
->flags
, LS_ATTR_DELAY
)
283 && (l1
->extended
.delay
!= l2
->extended
.delay
))
285 if (CHECK_FLAG(l1
->flags
, LS_ATTR_MIN_MAX_DELAY
)
286 && ((l1
->extended
.min_delay
!= l2
->extended
.min_delay
)
287 || (l1
->extended
.max_delay
!= l2
->extended
.max_delay
)))
289 if (CHECK_FLAG(l1
->flags
, LS_ATTR_JITTER
)
290 && (l1
->extended
.jitter
!= l2
->extended
.jitter
))
292 if (CHECK_FLAG(l1
->flags
, LS_ATTR_PACKET_LOSS
)
293 && (l1
->extended
.pkt_loss
!= l2
->extended
.pkt_loss
))
295 if (CHECK_FLAG(l1
->flags
, LS_ATTR_AVA_BW
)
296 && (l1
->extended
.ava_bw
!= l2
->extended
.ava_bw
))
298 if (CHECK_FLAG(l1
->flags
, LS_ATTR_RSV_BW
)
299 && (l1
->extended
.rsv_bw
!= l2
->extended
.rsv_bw
))
301 if (CHECK_FLAG(l1
->flags
, LS_ATTR_USE_BW
)
302 && (l1
->extended
.used_bw
!= l2
->extended
.used_bw
))
304 for (int i
= 0; i
< LS_ADJ_MAX
; i
++) {
305 if (!CHECK_FLAG(l1
->flags
, (LS_ATTR_ADJ_SID
<< i
)))
307 if ((l1
->adj_sid
[i
].sid
!= l2
->adj_sid
[i
].sid
)
308 || (l1
->adj_sid
[i
].flags
!= l2
->adj_sid
[i
].flags
)
309 || (l1
->adj_sid
[i
].weight
!= l2
->adj_sid
[i
].weight
))
311 if (((l1
->adv
.origin
== ISIS_L1
) || (l1
->adv
.origin
== ISIS_L2
))
312 && (memcmp(&l1
->adj_sid
[i
].neighbor
.sysid
,
313 &l2
->adj_sid
[i
].neighbor
.sysid
, ISO_SYS_ID_LEN
)
316 if (((l1
->adv
.origin
== OSPFv2
) || (l1
->adv
.origin
== STATIC
)
317 || (l1
->adv
.origin
== DIRECT
))
318 && (i
< ADJ_PRI_IPV6
)
319 && (!IPV4_ADDR_SAME(&l1
->adj_sid
[i
].neighbor
.addr
,
320 &l2
->adj_sid
[i
].neighbor
.addr
)))
323 if (CHECK_FLAG(l1
->flags
, LS_ATTR_SRLG
)
324 && ((l1
->srlg_len
!= l2
->srlg_len
)
325 || memcmp(l1
->srlgs
, l2
->srlgs
,
326 l1
->srlg_len
* sizeof(uint32_t))
330 /* OK, l1 & l2 are equal */
335 * Link State prefix management functions
337 struct ls_prefix
*ls_prefix_new(struct ls_node_id adv
, struct prefix
*p
)
339 struct ls_prefix
*new;
341 if (adv
.origin
== UNKNOWN
)
344 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_prefix
));
351 void ls_prefix_del(struct ls_prefix
*pref
)
356 XFREE(MTYPE_LS_DB
, pref
);
359 int ls_prefix_same(struct ls_prefix
*p1
, struct ls_prefix
*p2
)
361 /* First, check pointer */
362 if ((p1
&& !p2
) || (!p1
&& p2
))
368 /* Then, verify Flags and Origin */
369 if (p1
->flags
!= p2
->flags
)
372 if (!ls_node_id_same(p1
->adv
, p2
->adv
))
375 /* Finally, check each individual parameters that are valid */
376 if (prefix_same(&p1
->pref
, &p2
->pref
) == 0)
378 if (CHECK_FLAG(p1
->flags
, LS_PREF_IGP_FLAG
)
379 && (p1
->igp_flag
!= p2
->igp_flag
))
381 if (CHECK_FLAG(p1
->flags
, LS_PREF_ROUTE_TAG
)
382 && (p1
->route_tag
!= p2
->route_tag
))
384 if (CHECK_FLAG(p1
->flags
, LS_PREF_EXTENDED_TAG
)
385 && (p1
->extended_tag
!= p2
->extended_tag
))
387 if (CHECK_FLAG(p1
->flags
, LS_PREF_METRIC
) && (p1
->metric
!= p2
->metric
))
389 if (CHECK_FLAG(p1
->flags
, LS_PREF_SR
)) {
390 if ((p1
->sr
.algo
!= p2
->sr
.algo
) || (p1
->sr
.sid
!= p2
->sr
.sid
)
391 || (p1
->sr
.sid_flag
!= p2
->sr
.sid_flag
))
395 /* OK, p1 & p2 are equal */
400 * Link State Vertices management functions
402 uint64_t sysid_to_key(const uint8_t sysid
[ISO_SYS_ID_LEN
])
406 #if BYTE_ORDER == LITTLE_ENDIAN
407 uint8_t *byte
= (uint8_t *)&key
;
409 for (int i
= 0; i
< ISO_SYS_ID_LEN
; i
++)
410 byte
[i
] = sysid
[ISO_SYS_ID_LEN
- i
- 1];
415 memcpy(&key
, sysid
, ISO_SYS_ID_LEN
);
421 struct ls_vertex
*ls_vertex_add(struct ls_ted
*ted
, struct ls_node
*node
)
423 struct ls_vertex
*new;
426 if ((ted
== NULL
) || (node
== NULL
))
429 /* set Key as the IPv4/Ipv6 Router ID or ISO System ID */
430 switch (node
->adv
.origin
) {
434 key
= ((uint64_t)ntohl(node
->adv
.id
.ip
.addr
.s_addr
))
439 key
= sysid_to_key(node
->adv
.id
.iso
.sys_id
);
446 /* Check that key is valid */
450 /* Create Vertex and add it to the TED */
451 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_vertex
));
459 new->incoming_edges
= list_new();
460 new->incoming_edges
->cmp
= (int (*)(void *, void *))edge_cmp
;
461 new->outgoing_edges
= list_new();
462 new->outgoing_edges
->cmp
= (int (*)(void *, void *))edge_cmp
;
463 new->prefixes
= list_new();
464 new->prefixes
->cmp
= (int (*)(void *, void *))subnet_cmp
;
465 vertices_add(&ted
->vertices
, new);
470 void ls_vertex_del(struct ls_ted
*ted
, struct ls_vertex
*vertex
)
472 struct listnode
*node
, *nnode
;
473 struct ls_edge
*edge
;
474 struct ls_subnet
*subnet
;
479 /* Remove outgoing Edges and list */
480 for (ALL_LIST_ELEMENTS(vertex
->outgoing_edges
, node
, nnode
, edge
))
481 ls_edge_del_all(ted
, edge
);
482 list_delete(&vertex
->outgoing_edges
);
484 /* Disconnect incoming Edges and remove list */
485 for (ALL_LIST_ELEMENTS(vertex
->incoming_edges
, node
, nnode
, edge
)) {
486 ls_disconnect(vertex
, edge
, false);
487 if (edge
->source
== NULL
)
488 ls_edge_del_all(ted
, edge
);
490 list_delete(&vertex
->incoming_edges
);
492 /* Remove subnet and list */
493 for (ALL_LIST_ELEMENTS(vertex
->prefixes
, node
, nnode
, subnet
))
494 ls_subnet_del_all(ted
, subnet
);
495 list_delete(&vertex
->prefixes
);
497 /* Then remove Vertex from Link State Data Base and free memory */
498 vertices_del(&ted
->vertices
, vertex
);
499 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 struct ls_edge_key
get_edge_key(struct ls_attributes
*attr
, bool dst
)
678 struct ls_edge_key key
= {.family
= AF_UNSPEC
};
679 struct ls_standard
*std
;
684 std
= &attr
->standard
;
687 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
)) {
688 /* Key is the IPv4 remote address */
689 key
.family
= AF_INET
;
690 IPV4_ADDR_COPY(&key
.k
.addr
, &std
->remote
);
691 } else if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
)) {
692 /* or the IPv6 remote address */
693 key
.family
= AF_INET6
;
694 IPV6_ADDR_COPY(&key
.k
.addr6
, &std
->remote6
);
695 } else if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
)) {
696 /* or Remote identifier if IP addr. are not defined */
697 key
.family
= AF_LOCAL
;
699 (((uint64_t)std
->remote_id
) & 0xffffffff) |
700 ((uint64_t)std
->local_id
<< 32);
703 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)) {
704 /* Key is the IPv4 local address */
705 key
.family
= AF_INET
;
706 IPV4_ADDR_COPY(&key
.k
.addr
, &std
->local
);
707 } else if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)) {
708 /* or the 64 bits LSB of IPv6 local address */
709 key
.family
= AF_INET6
;
710 IPV6_ADDR_COPY(&key
.k
.addr6
, &std
->local6
);
711 } else if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
)) {
712 /* or Remote identifier if IP addr. are not defined */
713 key
.family
= AF_LOCAL
;
715 (((uint64_t)std
->local_id
) & 0xffffffff) |
716 ((uint64_t)std
->remote_id
<< 32);
723 struct ls_edge
*ls_edge_add(struct ls_ted
*ted
,
724 struct ls_attributes
*attributes
)
727 struct ls_edge_key key
;
729 if (attributes
== NULL
)
732 key
= get_edge_key(attributes
, false);
733 if (key
.family
== AF_UNSPEC
)
736 /* Create Edge and add it to the TED */
737 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_edge
));
739 new->attributes
= attributes
;
743 edges_add(&ted
->edges
, new);
745 /* Finally, connect Edge to Vertices */
746 ls_edge_connect_to(ted
, new);
751 struct ls_edge
*ls_find_edge_by_key(struct ls_ted
*ted
,
752 const struct ls_edge_key key
)
754 struct ls_edge edge
= {};
756 if (key
.family
== AF_UNSPEC
)
760 return edges_find(&ted
->edges
, &edge
);
763 struct ls_edge
*ls_find_edge_by_source(struct ls_ted
*ted
,
764 struct ls_attributes
*attributes
)
766 struct ls_edge edge
= {};
768 if (attributes
== NULL
)
771 edge
.key
= get_edge_key(attributes
, false);
772 if (edge
.key
.family
== AF_UNSPEC
)
775 return edges_find(&ted
->edges
, &edge
);
778 struct ls_edge
*ls_find_edge_by_destination(struct ls_ted
*ted
,
779 struct ls_attributes
*attributes
)
781 struct ls_edge edge
= {};
783 if (attributes
== NULL
)
786 edge
.key
= get_edge_key(attributes
, true);
787 if (edge
.key
.family
== AF_UNSPEC
)
790 return edges_find(&ted
->edges
, &edge
);
793 struct ls_edge
*ls_edge_update(struct ls_ted
*ted
,
794 struct ls_attributes
*attributes
)
798 if (attributes
== NULL
)
801 /* First, search for an existing Edge */
802 old
= ls_find_edge_by_source(ted
, attributes
);
804 /* Check if attributes are similar */
805 if (!ls_attributes_same(old
->attributes
, attributes
)) {
806 ls_attributes_del(old
->attributes
);
807 old
->attributes
= attributes
;
809 old
->status
= UPDATE
;
813 /* If not found, add new Edge from the attributes */
814 return ls_edge_add(ted
, attributes
);
817 int ls_edge_same(struct ls_edge
*e1
, struct ls_edge
*e2
)
819 if ((e1
&& !e2
) || (!e1
&& e2
))
825 if (edge_cmp(e1
, e2
) != 0)
828 if (e1
->attributes
== e2
->attributes
)
831 return ls_attributes_same(e1
->attributes
, e2
->attributes
);
834 void ls_edge_del(struct ls_ted
*ted
, struct ls_edge
*edge
)
839 /* Fist disconnect Edge from Vertices */
840 ls_disconnect_edge(edge
);
841 /* Then remove it from the Data Base */
842 edges_del(&ted
->edges
, edge
);
843 XFREE(MTYPE_LS_DB
, edge
);
846 void ls_edge_del_all(struct ls_ted
*ted
, struct ls_edge
*edge
)
851 /* Remove associated Link State Attributes */
852 ls_attributes_del(edge
->attributes
);
853 /* Then Edge itself */
854 ls_edge_del(ted
, edge
);
858 * Link State Subnet Management functions.
860 struct ls_subnet
*ls_subnet_add(struct ls_ted
*ted
,
861 struct ls_prefix
*ls_pref
)
863 struct ls_subnet
*new;
864 struct ls_vertex
*vertex
;
865 struct ls_node
*node
;
866 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
871 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_subnet
));
872 new->ls_pref
= ls_pref
;
873 new->key
= ls_pref
->pref
;
878 vertex
= ls_find_vertex_by_id(ted
, ls_pref
->adv
);
879 if (vertex
== NULL
) {
880 /* Create a new temporary Node & Vertex if not found */
881 node
= ls_node_new(ls_pref
->adv
, inaddr_any
, in6addr_any
);
882 vertex
= ls_vertex_add(ted
, node
);
884 /* And attach the subnet to the corresponding Vertex */
885 new->vertex
= vertex
;
886 listnode_add_sort_nodup(vertex
->prefixes
, new);
888 subnets_add(&ted
->subnets
, new);
893 struct ls_subnet
*ls_subnet_update(struct ls_ted
*ted
, struct ls_prefix
*pref
)
895 struct ls_subnet
*old
;
900 old
= ls_find_subnet(ted
, &pref
->pref
);
902 if (!ls_prefix_same(old
->ls_pref
, pref
)) {
903 ls_prefix_del(old
->ls_pref
);
906 old
->status
= UPDATE
;
910 return ls_subnet_add(ted
, pref
);
913 int ls_subnet_same(struct ls_subnet
*s1
, struct ls_subnet
*s2
)
915 if ((s1
&& !s2
) || (!s1
&& s2
))
921 if (!prefix_same(&s1
->key
, &s2
->key
))
924 if (s1
->ls_pref
== s2
->ls_pref
)
927 return ls_prefix_same(s1
->ls_pref
, s2
->ls_pref
);
930 void ls_subnet_del(struct ls_ted
*ted
, struct ls_subnet
*subnet
)
935 /* First, disconnect Subnet from associated Vertex */
936 listnode_delete(subnet
->vertex
->prefixes
, subnet
);
937 /* Then delete Subnet */
938 subnets_del(&ted
->subnets
, subnet
);
939 XFREE(MTYPE_LS_DB
, subnet
);
942 void ls_subnet_del_all(struct ls_ted
*ted
, struct ls_subnet
*subnet
)
947 /* First, remove associated Link State Subnet */
948 ls_prefix_del(subnet
->ls_pref
);
949 /* Then, delete Subnet itself */
950 ls_subnet_del(ted
, subnet
);
953 struct ls_subnet
*ls_find_subnet(struct ls_ted
*ted
,
954 const struct prefix
*prefix
)
956 struct ls_subnet subnet
= {};
961 prefix_copy(&subnet
.key
, prefix
);
962 return subnets_find(&ted
->subnets
, &subnet
);
966 * Link State TED management functions
968 struct ls_ted
*ls_ted_new(const uint32_t key
, const char *name
,
973 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_ted
));
975 /* Set basic information for this ted */
977 new->as_number
= as_number
;
978 strlcpy(new->name
, name
, MAX_NAME_LENGTH
);
980 /* Initialize the various RB tree */
981 vertices_init(&new->vertices
);
982 edges_init(&new->edges
);
983 subnets_init(&new->subnets
);
988 void ls_ted_del(struct ls_ted
*ted
)
993 /* Check that TED is empty */
994 if (vertices_count(&ted
->vertices
) || edges_count(&ted
->edges
)
995 || subnets_count(&ted
->subnets
))
998 /* Release RB Tree */
999 vertices_fini(&ted
->vertices
);
1000 edges_fini(&ted
->edges
);
1001 subnets_fini(&ted
->subnets
);
1003 XFREE(MTYPE_LS_DB
, ted
);
1006 void ls_ted_del_all(struct ls_ted
**ted
)
1008 struct ls_vertex
*vertex
;
1009 struct ls_edge
*edge
;
1010 struct ls_subnet
*subnet
;
1015 /* First remove Vertices, Edges and Subnets and associated Link State */
1016 frr_each_safe (vertices
, &(*ted
)->vertices
, vertex
)
1017 ls_vertex_del_all(*ted
, vertex
);
1018 frr_each_safe (edges
, &(*ted
)->edges
, edge
)
1019 ls_edge_del_all(*ted
, edge
);
1020 frr_each_safe (subnets
, &(*ted
)->subnets
, subnet
)
1021 ls_subnet_del_all(*ted
, subnet
);
1023 /* then remove TED itself */
1028 void ls_ted_clean(struct ls_ted
*ted
)
1030 struct ls_vertex
*vertex
;
1031 struct ls_edge
*edge
;
1032 struct ls_subnet
*subnet
;
1037 /* First, start with Vertices */
1038 frr_each_safe (vertices
, &ted
->vertices
, vertex
)
1039 if (vertex
->status
== ORPHAN
)
1040 ls_vertex_del_all(ted
, vertex
);
1043 frr_each_safe (edges
, &ted
->edges
, edge
)
1044 if (edge
->status
== ORPHAN
)
1045 ls_edge_del_all(ted
, edge
);
1048 frr_each_safe (subnets
, &ted
->subnets
, subnet
)
1049 if (subnet
->status
== ORPHAN
)
1050 ls_subnet_del_all(ted
, subnet
);
1054 void ls_connect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
1056 if (vertex
== NULL
|| edge
== NULL
)
1060 listnode_add_sort_nodup(vertex
->outgoing_edges
, edge
);
1061 edge
->source
= vertex
;
1063 listnode_add_sort_nodup(vertex
->incoming_edges
, edge
);
1064 edge
->destination
= vertex
;
1068 void ls_disconnect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
1071 if (vertex
== NULL
|| edge
== NULL
)
1075 listnode_delete(vertex
->outgoing_edges
, edge
);
1076 edge
->source
= NULL
;
1078 listnode_delete(vertex
->incoming_edges
, edge
);
1079 edge
->destination
= NULL
;
1083 void ls_connect_vertices(struct ls_vertex
*src
, struct ls_vertex
*dst
,
1084 struct ls_edge
*edge
)
1090 edge
->destination
= dst
;
1093 listnode_add_sort_nodup(src
->outgoing_edges
, edge
);
1096 listnode_add_sort_nodup(dst
->incoming_edges
, edge
);
1099 void ls_disconnect_edge(struct ls_edge
*edge
)
1104 ls_disconnect(edge
->source
, edge
, true);
1105 ls_disconnect(edge
->destination
, edge
, false);
1107 /* Mark this Edge as ORPHAN for future cleanup */
1108 edge
->status
= ORPHAN
;
1112 * Link State Message management functions
1115 int ls_register(struct zclient
*zclient
, bool server
)
1120 rc
= zclient_register_opaque(zclient
, LINK_STATE_SYNC
);
1122 rc
= zclient_register_opaque(zclient
, LINK_STATE_UPDATE
);
1127 int ls_unregister(struct zclient
*zclient
, bool server
)
1132 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_SYNC
);
1134 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_UPDATE
);
1139 int ls_request_sync(struct zclient
*zclient
)
1144 /* Check buffer size */
1145 if (STREAM_SIZE(zclient
->obuf
)
1146 < (ZEBRA_HEADER_SIZE
+ 3 * sizeof(uint32_t)))
1152 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
1154 /* Set type and flags */
1155 stream_putl(s
, LINK_STATE_SYNC
);
1156 stream_putw(s
, flags
);
1157 /* Send destination client info */
1158 stream_putc(s
, zclient
->redist_default
);
1159 stream_putw(s
, zclient
->instance
);
1160 stream_putl(s
, zclient
->session_id
);
1162 /* Put length into the header at the start of the stream. */
1163 stream_putw_at(s
, 0, stream_get_endp(s
));
1165 return zclient_send_message(zclient
);
1168 static struct ls_node
*ls_parse_node(struct stream
*s
)
1170 struct ls_node
*node
;
1173 node
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
1175 STREAM_GET(&node
->adv
, s
, sizeof(struct ls_node_id
));
1176 STREAM_GETW(s
, node
->flags
);
1177 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1178 STREAM_GETC(s
, len
);
1179 STREAM_GET(node
->name
, s
, len
);
1181 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1182 node
->router_id
.s_addr
= stream_get_ipv4(s
);
1183 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1184 STREAM_GET(&node
->router_id6
, s
, IPV6_MAX_BYTELEN
);
1185 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1186 STREAM_GETC(s
, node
->node_flag
);
1187 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1188 STREAM_GETC(s
, node
->type
);
1189 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1190 STREAM_GETL(s
, node
->as_number
);
1191 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1192 STREAM_GETL(s
, node
->srgb
.lower_bound
);
1193 STREAM_GETL(s
, node
->srgb
.range_size
);
1194 STREAM_GETC(s
, node
->srgb
.flag
);
1195 STREAM_GET(node
->algo
, s
, 2);
1197 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1198 STREAM_GETL(s
, node
->srlb
.lower_bound
);
1199 STREAM_GETL(s
, node
->srlb
.range_size
);
1201 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1202 STREAM_GETC(s
, node
->msd
);
1207 zlog_err("LS(%s): Could not parse Link State Node. Abort!", __func__
);
1208 XFREE(MTYPE_LS_DB
, node
);
1212 static struct ls_attributes
*ls_parse_attributes(struct stream
*s
)
1214 struct ls_attributes
*attr
;
1215 uint8_t nb_ext_adm_grp
;
1216 uint32_t bitmap_data
;
1219 attr
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
1220 admin_group_init(&attr
->ext_admin_group
);
1223 STREAM_GET(&attr
->adv
, s
, sizeof(struct ls_node_id
));
1224 STREAM_GETL(s
, attr
->flags
);
1225 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1226 STREAM_GETC(s
, len
);
1227 STREAM_GET(attr
->name
, s
, len
);
1229 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1230 STREAM_GETL(s
, attr
->metric
);
1231 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1232 STREAM_GETL(s
, attr
->standard
.te_metric
);
1233 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1234 STREAM_GETL(s
, attr
->standard
.admin_group
);
1235 if (CHECK_FLAG(attr
->flags
, LS_ATTR_EXT_ADM_GRP
)) {
1236 /* Extended Administrative Group */
1237 STREAM_GETC(s
, nb_ext_adm_grp
);
1238 for (size_t i
= 0; i
< nb_ext_adm_grp
; i
++) {
1239 STREAM_GETL(s
, bitmap_data
);
1240 admin_group_bulk_set(&attr
->ext_admin_group
,
1244 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1245 attr
->standard
.local
.s_addr
= stream_get_ipv4(s
);
1246 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1247 attr
->standard
.remote
.s_addr
= stream_get_ipv4(s
);
1248 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1249 STREAM_GET(&attr
->standard
.local6
, s
, IPV6_MAX_BYTELEN
);
1250 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1251 STREAM_GET(&attr
->standard
.remote6
, s
, IPV6_MAX_BYTELEN
);
1252 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1253 STREAM_GETL(s
, attr
->standard
.local_id
);
1254 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1255 STREAM_GETL(s
, attr
->standard
.remote_id
);
1256 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1257 STREAM_GETF(s
, attr
->standard
.max_bw
);
1258 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1259 STREAM_GETF(s
, attr
->standard
.max_rsv_bw
);
1260 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1261 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1262 STREAM_GETF(s
, attr
->standard
.unrsv_bw
[len
]);
1263 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1264 STREAM_GETL(s
, attr
->standard
.remote_as
);
1265 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1266 attr
->standard
.remote_addr
.s_addr
= stream_get_ipv4(s
);
1267 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1268 STREAM_GET(&attr
->standard
.remote_addr6
, s
, IPV6_MAX_BYTELEN
);
1269 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1270 STREAM_GETL(s
, attr
->extended
.delay
);
1271 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1272 STREAM_GETL(s
, attr
->extended
.min_delay
);
1273 STREAM_GETL(s
, attr
->extended
.max_delay
);
1275 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1276 STREAM_GETL(s
, attr
->extended
.jitter
);
1277 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1278 STREAM_GETL(s
, attr
->extended
.pkt_loss
);
1279 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1280 STREAM_GETF(s
, attr
->extended
.ava_bw
);
1281 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1282 STREAM_GETF(s
, attr
->extended
.rsv_bw
);
1283 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1284 STREAM_GETF(s
, attr
->extended
.used_bw
);
1285 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1286 STREAM_GETL(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
1287 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].flags
);
1288 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
1289 attr
->adj_sid
[ADJ_PRI_IPV4
].neighbor
.addr
.s_addr
=
1292 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1293 STREAM_GETL(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
1294 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].flags
);
1295 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
1296 attr
->adj_sid
[ADJ_BCK_IPV4
].neighbor
.addr
.s_addr
=
1299 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
1300 STREAM_GETL(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
1301 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].flags
);
1302 STREAM_GETC(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
1303 STREAM_GET(attr
->adj_sid
[ADJ_PRI_IPV6
].neighbor
.sysid
, s
,
1306 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
1307 STREAM_GETL(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
1308 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].flags
);
1309 STREAM_GETC(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
1310 STREAM_GET(attr
->adj_sid
[ADJ_BCK_IPV6
].neighbor
.sysid
, s
,
1313 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1314 STREAM_GETC(s
, len
);
1315 attr
->srlgs
= XCALLOC(MTYPE_LS_DB
, len
*sizeof(uint32_t));
1316 attr
->srlg_len
= len
;
1317 for (len
= 0; len
< attr
->srlg_len
; len
++)
1318 STREAM_GETL(s
, attr
->srlgs
[len
]);
1324 zlog_err("LS(%s): Could not parse Link State Attributes. Abort!",
1326 /* Clean memory allocation */
1327 if (attr
->srlgs
!= NULL
)
1328 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
1329 XFREE(MTYPE_LS_DB
, attr
);
1334 static struct ls_prefix
*ls_parse_prefix(struct stream
*s
)
1336 struct ls_prefix
*ls_pref
;
1339 ls_pref
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_prefix
));
1341 STREAM_GET(&ls_pref
->adv
, s
, sizeof(struct ls_node_id
));
1342 STREAM_GETW(s
, ls_pref
->flags
);
1343 STREAM_GETC(s
, ls_pref
->pref
.family
);
1344 STREAM_GETW(s
, ls_pref
->pref
.prefixlen
);
1345 len
= prefix_blen(&ls_pref
->pref
);
1346 STREAM_GET(&ls_pref
->pref
.u
.prefix
, s
, len
);
1347 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1348 STREAM_GETC(s
, ls_pref
->igp_flag
);
1349 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1350 STREAM_GETL(s
, ls_pref
->route_tag
);
1351 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1352 STREAM_GETQ(s
, ls_pref
->extended_tag
);
1353 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1354 STREAM_GETL(s
, ls_pref
->metric
);
1355 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1356 STREAM_GETL(s
, ls_pref
->sr
.sid
);
1357 STREAM_GETC(s
, ls_pref
->sr
.sid_flag
);
1358 STREAM_GETC(s
, ls_pref
->sr
.algo
);
1364 zlog_err("LS(%s): Could not parse Link State Prefix. Abort!", __func__
);
1365 XFREE(MTYPE_LS_DB
, ls_pref
);
1369 struct ls_message
*ls_parse_msg(struct stream
*s
)
1371 struct ls_message
*msg
;
1373 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1375 /* Read LS Message header */
1376 STREAM_GETC(s
, msg
->event
);
1377 STREAM_GETC(s
, msg
->type
);
1379 /* Read Message Payload */
1380 switch (msg
->type
) {
1381 case LS_MSG_TYPE_NODE
:
1382 msg
->data
.node
= ls_parse_node(s
);
1384 case LS_MSG_TYPE_ATTRIBUTES
:
1385 STREAM_GET(&msg
->remote_id
, s
, sizeof(struct ls_node_id
));
1386 msg
->data
.attr
= ls_parse_attributes(s
);
1388 case LS_MSG_TYPE_PREFIX
:
1389 msg
->data
.prefix
= ls_parse_prefix(s
);
1392 zlog_err("Unsupported Payload");
1393 goto stream_failure
;
1396 if (msg
->data
.node
== NULL
|| msg
->data
.attr
== NULL
1397 || msg
->data
.prefix
== NULL
)
1398 goto stream_failure
;
1403 zlog_err("LS(%s): Could not parse LS message. Abort!", __func__
);
1404 XFREE(MTYPE_LS_DB
, msg
);
1408 static int ls_format_node(struct stream
*s
, struct ls_node
*node
)
1412 /* Push Advertise node information first */
1413 stream_put(s
, &node
->adv
, sizeof(struct ls_node_id
));
1415 /* Push Flags & Origin then Node information if there are present */
1416 stream_putw(s
, node
->flags
);
1417 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1418 len
= strlen(node
->name
);
1419 stream_putc(s
, len
+ 1);
1420 stream_put(s
, node
->name
, len
);
1421 stream_putc(s
, '\0');
1423 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1424 stream_put_ipv4(s
, node
->router_id
.s_addr
);
1425 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1426 stream_put(s
, &node
->router_id6
, IPV6_MAX_BYTELEN
);
1427 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1428 stream_putc(s
, node
->node_flag
);
1429 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1430 stream_putc(s
, node
->type
);
1431 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1432 stream_putl(s
, node
->as_number
);
1433 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1434 stream_putl(s
, node
->srgb
.lower_bound
);
1435 stream_putl(s
, node
->srgb
.range_size
);
1436 stream_putc(s
, node
->srgb
.flag
);
1437 stream_put(s
, node
->algo
, 2);
1439 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1440 stream_putl(s
, node
->srlb
.lower_bound
);
1441 stream_putl(s
, node
->srlb
.range_size
);
1443 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1444 stream_putc(s
, node
->msd
);
1449 static int ls_format_attributes(struct stream
*s
, struct ls_attributes
*attr
)
1451 size_t len
, nb_ext_adm_grp
;
1453 /* Push Advertise node information first */
1454 stream_put(s
, &attr
->adv
, sizeof(struct ls_node_id
));
1456 /* Push Flags & Origin then LS attributes if there are present */
1457 stream_putl(s
, attr
->flags
);
1458 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1459 len
= strlen(attr
->name
);
1460 stream_putc(s
, len
+ 1);
1461 stream_put(s
, attr
->name
, len
);
1462 stream_putc(s
, '\0');
1464 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1465 stream_putl(s
, attr
->metric
);
1466 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1467 stream_putl(s
, attr
->standard
.te_metric
);
1468 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1469 stream_putl(s
, attr
->standard
.admin_group
);
1470 if (CHECK_FLAG(attr
->flags
, LS_ATTR_EXT_ADM_GRP
)) {
1471 /* Extended Administrative Group */
1472 nb_ext_adm_grp
= admin_group_nb_words(&attr
->ext_admin_group
);
1473 stream_putc(s
, nb_ext_adm_grp
);
1474 for (size_t i
= 0; i
< nb_ext_adm_grp
; i
++)
1475 stream_putl(s
, admin_group_get_offset(
1476 &attr
->ext_admin_group
, i
));
1478 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1479 stream_put_ipv4(s
, attr
->standard
.local
.s_addr
);
1480 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1481 stream_put_ipv4(s
, attr
->standard
.remote
.s_addr
);
1482 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1483 stream_put(s
, &attr
->standard
.local6
, IPV6_MAX_BYTELEN
);
1484 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1485 stream_put(s
, &attr
->standard
.remote6
, IPV6_MAX_BYTELEN
);
1486 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1487 stream_putl(s
, attr
->standard
.local_id
);
1488 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1489 stream_putl(s
, attr
->standard
.remote_id
);
1490 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1491 stream_putf(s
, attr
->standard
.max_bw
);
1492 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1493 stream_putf(s
, attr
->standard
.max_rsv_bw
);
1494 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1495 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1496 stream_putf(s
, attr
->standard
.unrsv_bw
[len
]);
1497 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1498 stream_putl(s
, attr
->standard
.remote_as
);
1499 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1500 stream_put_ipv4(s
, attr
->standard
.remote_addr
.s_addr
);
1501 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1502 stream_put(s
, &attr
->standard
.remote_addr6
, IPV6_MAX_BYTELEN
);
1503 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1504 stream_putl(s
, attr
->extended
.delay
);
1505 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1506 stream_putl(s
, attr
->extended
.min_delay
);
1507 stream_putl(s
, attr
->extended
.max_delay
);
1509 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1510 stream_putl(s
, attr
->extended
.jitter
);
1511 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1512 stream_putl(s
, attr
->extended
.pkt_loss
);
1513 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1514 stream_putf(s
, attr
->extended
.ava_bw
);
1515 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1516 stream_putf(s
, attr
->extended
.rsv_bw
);
1517 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1518 stream_putf(s
, attr
->extended
.used_bw
);
1519 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1520 stream_putl(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
1521 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].flags
);
1522 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
1524 s
, attr
->adj_sid
[ADJ_PRI_IPV4
].neighbor
.addr
.s_addr
);
1526 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1527 stream_putl(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
1528 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].flags
);
1529 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
1531 s
, attr
->adj_sid
[ADJ_BCK_IPV4
].neighbor
.addr
.s_addr
);
1533 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
1534 stream_putl(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
1535 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].flags
);
1536 stream_putc(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
1537 stream_put(s
, attr
->adj_sid
[ADJ_PRI_IPV6
].neighbor
.sysid
,
1540 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
1541 stream_putl(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
1542 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].flags
);
1543 stream_putc(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
1544 stream_put(s
, attr
->adj_sid
[ADJ_BCK_IPV6
].neighbor
.sysid
,
1547 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1548 stream_putc(s
, attr
->srlg_len
);
1549 for (len
= 0; len
< attr
->srlg_len
; len
++)
1550 stream_putl(s
, attr
->srlgs
[len
]);
1556 static int ls_format_prefix(struct stream
*s
, struct ls_prefix
*ls_pref
)
1560 /* Push Advertise node information first */
1561 stream_put(s
, &ls_pref
->adv
, sizeof(struct ls_node_id
));
1563 /* Push Flags, Origin & Prefix then information if there are present */
1564 stream_putw(s
, ls_pref
->flags
);
1565 stream_putc(s
, ls_pref
->pref
.family
);
1566 stream_putw(s
, ls_pref
->pref
.prefixlen
);
1567 len
= prefix_blen(&ls_pref
->pref
);
1568 stream_put(s
, &ls_pref
->pref
.u
.prefix
, len
);
1569 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1570 stream_putc(s
, ls_pref
->igp_flag
);
1571 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1572 stream_putl(s
, ls_pref
->route_tag
);
1573 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1574 stream_putq(s
, ls_pref
->extended_tag
);
1575 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1576 stream_putl(s
, ls_pref
->metric
);
1577 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1578 stream_putl(s
, ls_pref
->sr
.sid
);
1579 stream_putc(s
, ls_pref
->sr
.sid_flag
);
1580 stream_putc(s
, ls_pref
->sr
.algo
);
1586 static int ls_format_msg(struct stream
*s
, struct ls_message
*msg
)
1589 /* Prepare Link State header */
1590 stream_putc(s
, msg
->event
);
1591 stream_putc(s
, msg
->type
);
1593 /* Add Message Payload */
1594 switch (msg
->type
) {
1595 case LS_MSG_TYPE_NODE
:
1596 return ls_format_node(s
, msg
->data
.node
);
1597 case LS_MSG_TYPE_ATTRIBUTES
:
1598 /* Add remote node first */
1599 stream_put(s
, &msg
->remote_id
, sizeof(struct ls_node_id
));
1600 return ls_format_attributes(s
, msg
->data
.attr
);
1601 case LS_MSG_TYPE_PREFIX
:
1602 return ls_format_prefix(s
, msg
->data
.prefix
);
1604 zlog_warn("Unsupported Payload");
1611 int ls_send_msg(struct zclient
*zclient
, struct ls_message
*msg
,
1612 struct zapi_opaque_reg_info
*dst
)
1617 /* Check if we have a valid message */
1618 if (msg
->event
== LS_MSG_EVENT_UNDEF
)
1621 /* Check buffer size */
1622 if (STREAM_SIZE(zclient
->obuf
) <
1623 (ZEBRA_HEADER_SIZE
+ sizeof(uint32_t) + sizeof(msg
)))
1629 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
1631 /* Set sub-type, flags and destination for unicast message */
1632 stream_putl(s
, LINK_STATE_UPDATE
);
1634 SET_FLAG(flags
, ZAPI_OPAQUE_FLAG_UNICAST
);
1635 stream_putw(s
, flags
);
1636 /* Send destination client info */
1637 stream_putc(s
, dst
->proto
);
1638 stream_putw(s
, dst
->instance
);
1639 stream_putl(s
, dst
->session_id
);
1641 stream_putw(s
, flags
);
1644 /* Format Link State message */
1645 if (ls_format_msg(s
, msg
) < 0) {
1650 /* Put length into the header at the start of the stream. */
1651 stream_putw_at(s
, 0, stream_get_endp(s
));
1653 return zclient_send_message(zclient
);
1655 struct ls_message
*ls_vertex2msg(struct ls_message
*msg
,
1656 struct ls_vertex
*vertex
)
1658 /* Allocate space if needed */
1660 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1662 memset(msg
, 0, sizeof(*msg
));
1664 msg
->type
= LS_MSG_TYPE_NODE
;
1665 switch (vertex
->status
) {
1667 msg
->event
= LS_MSG_EVENT_ADD
;
1670 msg
->event
= LS_MSG_EVENT_UPDATE
;
1673 msg
->event
= LS_MSG_EVENT_DELETE
;
1676 msg
->event
= LS_MSG_EVENT_SYNC
;
1680 msg
->event
= LS_MSG_EVENT_UNDEF
;
1683 msg
->data
.node
= vertex
->node
;
1684 msg
->remote_id
.origin
= UNKNOWN
;
1689 struct ls_message
*ls_edge2msg(struct ls_message
*msg
, struct ls_edge
*edge
)
1691 /* Allocate space if needed */
1693 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1695 memset(msg
, 0, sizeof(*msg
));
1697 msg
->type
= LS_MSG_TYPE_ATTRIBUTES
;
1698 switch (edge
->status
) {
1700 msg
->event
= LS_MSG_EVENT_ADD
;
1703 msg
->event
= LS_MSG_EVENT_UPDATE
;
1706 msg
->event
= LS_MSG_EVENT_DELETE
;
1709 msg
->event
= LS_MSG_EVENT_SYNC
;
1713 msg
->event
= LS_MSG_EVENT_UNDEF
;
1716 msg
->data
.attr
= edge
->attributes
;
1717 if (edge
->destination
!= NULL
)
1718 msg
->remote_id
= edge
->destination
->node
->adv
;
1720 msg
->remote_id
.origin
= UNKNOWN
;
1725 struct ls_message
*ls_subnet2msg(struct ls_message
*msg
,
1726 struct ls_subnet
*subnet
)
1728 /* Allocate space if needed */
1730 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1732 memset(msg
, 0, sizeof(*msg
));
1734 msg
->type
= LS_MSG_TYPE_PREFIX
;
1735 switch (subnet
->status
) {
1737 msg
->event
= LS_MSG_EVENT_ADD
;
1740 msg
->event
= LS_MSG_EVENT_UPDATE
;
1743 msg
->event
= LS_MSG_EVENT_DELETE
;
1746 msg
->event
= LS_MSG_EVENT_SYNC
;
1750 msg
->event
= LS_MSG_EVENT_UNDEF
;
1753 msg
->data
.prefix
= subnet
->ls_pref
;
1754 msg
->remote_id
.origin
= UNKNOWN
;
1759 struct ls_vertex
*ls_msg2vertex(struct ls_ted
*ted
, struct ls_message
*msg
,
1762 struct ls_node
*node
= (struct ls_node
*)msg
->data
.node
;
1763 struct ls_vertex
*vertex
= NULL
;
1765 switch (msg
->event
) {
1766 case LS_MSG_EVENT_SYNC
:
1767 vertex
= ls_vertex_add(ted
, node
);
1769 vertex
->status
= SYNC
;
1771 case LS_MSG_EVENT_ADD
:
1772 vertex
= ls_vertex_add(ted
, node
);
1774 vertex
->status
= NEW
;
1776 case LS_MSG_EVENT_UPDATE
:
1777 vertex
= ls_vertex_update(ted
, node
);
1779 vertex
->status
= UPDATE
;
1781 case LS_MSG_EVENT_DELETE
:
1782 vertex
= ls_find_vertex_by_id(ted
, node
->adv
);
1785 ls_vertex_del_all(ted
, vertex
);
1788 vertex
->status
= DELETE
;
1799 struct ls_edge
*ls_msg2edge(struct ls_ted
*ted
, struct ls_message
*msg
,
1802 struct ls_attributes
*attr
= (struct ls_attributes
*)msg
->data
.attr
;
1803 struct ls_edge
*edge
= NULL
;
1805 switch (msg
->event
) {
1806 case LS_MSG_EVENT_SYNC
:
1807 edge
= ls_edge_add(ted
, attr
);
1809 edge
->status
= SYNC
;
1811 case LS_MSG_EVENT_ADD
:
1812 edge
= ls_edge_add(ted
, attr
);
1816 case LS_MSG_EVENT_UPDATE
:
1817 edge
= ls_edge_update(ted
, attr
);
1819 edge
->status
= UPDATE
;
1821 case LS_MSG_EVENT_DELETE
:
1822 edge
= ls_find_edge_by_source(ted
, attr
);
1825 ls_edge_del_all(ted
, edge
);
1828 edge
->status
= DELETE
;
1839 struct ls_subnet
*ls_msg2subnet(struct ls_ted
*ted
, struct ls_message
*msg
,
1842 struct ls_prefix
*pref
= (struct ls_prefix
*)msg
->data
.prefix
;
1843 struct ls_subnet
*subnet
= NULL
;
1845 switch (msg
->event
) {
1846 case LS_MSG_EVENT_SYNC
:
1847 subnet
= ls_subnet_add(ted
, pref
);
1849 subnet
->status
= SYNC
;
1851 case LS_MSG_EVENT_ADD
:
1852 subnet
= ls_subnet_add(ted
, pref
);
1854 subnet
->status
= NEW
;
1856 case LS_MSG_EVENT_UPDATE
:
1857 subnet
= ls_subnet_update(ted
, pref
);
1859 subnet
->status
= UPDATE
;
1861 case LS_MSG_EVENT_DELETE
:
1862 subnet
= ls_find_subnet(ted
, &pref
->pref
);
1865 ls_subnet_del_all(ted
, subnet
);
1868 subnet
->status
= DELETE
;
1879 struct ls_element
*ls_msg2ted(struct ls_ted
*ted
, struct ls_message
*msg
,
1882 struct ls_element
*lse
= NULL
;
1884 switch (msg
->type
) {
1885 case LS_MSG_TYPE_NODE
:
1886 lse
= (struct ls_element
*)ls_msg2vertex(ted
, msg
, delete);
1888 case LS_MSG_TYPE_ATTRIBUTES
:
1889 lse
= (struct ls_element
*)ls_msg2edge(ted
, msg
, delete);
1891 case LS_MSG_TYPE_PREFIX
:
1892 lse
= (struct ls_element
*)ls_msg2subnet(ted
, msg
, delete);
1902 struct ls_element
*ls_stream2ted(struct ls_ted
*ted
, struct stream
*s
,
1905 struct ls_message
*msg
;
1906 struct ls_element
*lse
= NULL
;
1908 msg
= ls_parse_msg(s
);
1910 lse
= ls_msg2ted(ted
, msg
, delete);
1917 void ls_delete_msg(struct ls_message
*msg
)
1922 if (msg
->event
== LS_MSG_EVENT_DELETE
) {
1923 switch (msg
->type
) {
1924 case LS_MSG_TYPE_NODE
:
1925 ls_node_del(msg
->data
.node
);
1927 case LS_MSG_TYPE_ATTRIBUTES
:
1928 ls_attributes_del(msg
->data
.attr
);
1930 case LS_MSG_TYPE_PREFIX
:
1931 ls_prefix_del(msg
->data
.prefix
);
1936 XFREE(MTYPE_LS_DB
, msg
);
1939 int ls_sync_ted(struct ls_ted
*ted
, struct zclient
*zclient
,
1940 struct zapi_opaque_reg_info
*dst
)
1942 struct ls_vertex
*vertex
;
1943 struct ls_edge
*edge
;
1944 struct ls_subnet
*subnet
;
1945 struct ls_message msg
;
1947 /* Loop TED, start sending Node, then Attributes and finally Prefix */
1948 frr_each(vertices
, &ted
->vertices
, vertex
) {
1949 ls_vertex2msg(&msg
, vertex
);
1950 ls_send_msg(zclient
, &msg
, dst
);
1952 frr_each(edges
, &ted
->edges
, edge
) {
1953 ls_edge2msg(&msg
, edge
);
1954 ls_send_msg(zclient
, &msg
, dst
);
1956 frr_each(subnets
, &ted
->subnets
, subnet
) {
1957 ls_subnet2msg(&msg
, subnet
);
1958 ls_send_msg(zclient
, &msg
, dst
);
1964 * Link State Show functions
1966 static const char *const origin2txt
[] = {
1975 static const char *const type2txt
[] = {
1984 static const char *const status2txt
[] = {
1993 static const char *ls_node_id_to_text(struct ls_node_id lnid
, char *str
,
1996 if (lnid
.origin
== ISIS_L1
|| lnid
.origin
== ISIS_L2
)
1997 snprintfrr(str
, size
, "%pSY", lnid
.id
.iso
.sys_id
);
1999 snprintfrr(str
, size
, "%pI4", &lnid
.id
.ip
.addr
);
2004 static void ls_show_vertex_vty(struct ls_vertex
*vertex
, struct vty
*vty
,
2007 struct listnode
*node
;
2008 struct ls_node
*lsn
;
2009 struct ls_edge
*edge
;
2010 struct ls_attributes
*attr
;
2011 struct ls_subnet
*subnet
;
2021 sbuf_init(&sbuf
, NULL
, 0);
2023 sbuf_push(&sbuf
, 2, "Vertex (%" PRIu64
"): %s", vertex
->key
, lsn
->name
);
2024 sbuf_push(&sbuf
, 0, "\tRouter Id: %pI4", &lsn
->router_id
);
2025 sbuf_push(&sbuf
, 0, "\tOrigin: %s", origin2txt
[lsn
->adv
.origin
]);
2026 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[vertex
->status
]);
2030 "\t%d Outgoing Edges, %d Incoming Edges, %d Subnets\n",
2031 listcount(vertex
->outgoing_edges
),
2032 listcount(vertex
->incoming_edges
),
2033 listcount(vertex
->prefixes
));
2037 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
2038 sbuf_push(&sbuf
, 4, "Type: %s\n", type2txt
[lsn
->type
]);
2039 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
2040 sbuf_push(&sbuf
, 4, "AS number: %u\n", lsn
->as_number
);
2041 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
2042 sbuf_push(&sbuf
, 4, "Segment Routing Capabilities:\n");
2043 upper
= lsn
->srgb
.lower_bound
+ lsn
->srgb
.range_size
- 1;
2044 sbuf_push(&sbuf
, 8, "SRGB: [%d/%d]", lsn
->srgb
.lower_bound
,
2046 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
2047 upper
= lsn
->srlb
.lower_bound
+ lsn
->srlb
.range_size
2049 sbuf_push(&sbuf
, 0, "\tSRLB: [%d/%d]",
2050 lsn
->srlb
.lower_bound
, upper
);
2052 sbuf_push(&sbuf
, 0, "\tAlgo: ");
2053 for (int i
= 0; i
< 2; i
++) {
2054 if (lsn
->algo
[i
] == 255)
2058 lsn
->algo
[i
] == 0 ? "SPF " : "S-SPF ");
2060 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
2061 sbuf_push(&sbuf
, 0, "\tMSD: %d", lsn
->msd
);
2062 sbuf_push(&sbuf
, 0, "\n");
2065 sbuf_push(&sbuf
, 4, "Outgoing Edges: %d\n",
2066 listcount(vertex
->outgoing_edges
));
2067 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, node
, edge
)) {
2068 if (edge
->destination
) {
2069 lsn
= edge
->destination
->node
;
2070 sbuf_push(&sbuf
, 6, "To:\t%s(%pI4)", lsn
->name
,
2073 sbuf_push(&sbuf
, 6, "To:\t- (0.0.0.0)");
2075 attr
= edge
->attributes
;
2076 if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)))
2077 sbuf_push(&sbuf
, 0, "\tLocal: %pI4\tRemote: %pI4\n",
2078 &attr
->standard
.local
,
2079 &attr
->standard
.remote
);
2080 else if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)))
2081 sbuf_push(&sbuf
, 0, "\tLocal: %pI6\tRemote: %pI6\n",
2082 &attr
->standard
.local6
,
2083 &attr
->standard
.remote6
);
2086 sbuf_push(&sbuf
, 4, "Incoming Edges: %d\n",
2087 listcount(vertex
->incoming_edges
));
2088 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, node
, edge
)) {
2090 lsn
= edge
->source
->node
;
2091 sbuf_push(&sbuf
, 6, "From:\t%s(%pI4)", lsn
->name
,
2094 sbuf_push(&sbuf
, 6, "From:\t- (0.0.0.0)");
2096 attr
= edge
->attributes
;
2097 if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)))
2098 sbuf_push(&sbuf
, 0, "\tLocal: %pI4\tRemote: %pI4\n",
2099 &attr
->standard
.local
,
2100 &attr
->standard
.remote
);
2101 else if ((CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)))
2102 sbuf_push(&sbuf
, 0, "\tLocal: %pI6\tRemote: %pI6\n",
2103 &attr
->standard
.local6
,
2104 &attr
->standard
.remote6
);
2107 sbuf_push(&sbuf
, 4, "Subnets: %d\n", listcount(vertex
->prefixes
));
2108 for (ALL_LIST_ELEMENTS_RO(vertex
->prefixes
, node
, subnet
))
2109 sbuf_push(&sbuf
, 6, "Prefix:\t%pFX\n", &subnet
->key
);
2112 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2116 static void ls_show_vertex_json(struct ls_vertex
*vertex
,
2117 struct json_object
*json
)
2119 struct ls_node
*lsn
;
2120 json_object
*jsr
, *jalgo
, *jobj
;
2121 char buf
[INET6_BUFSIZ
];
2129 json_object_int_add(json
, "vertex-id", vertex
->key
);
2130 json_object_string_add(json
, "status", status2txt
[vertex
->status
]);
2131 json_object_string_add(json
, "origin", origin2txt
[lsn
->adv
.origin
]);
2132 if (CHECK_FLAG(lsn
->flags
, LS_NODE_NAME
))
2133 json_object_string_add(json
, "name", lsn
->name
);
2134 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID
)) {
2135 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &lsn
->router_id
);
2136 json_object_string_add(json
, "router-id", buf
);
2138 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID6
)) {
2139 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &lsn
->router_id6
);
2140 json_object_string_add(json
, "router-id-v6", buf
);
2142 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
2143 json_object_string_add(json
, "vertex-type",
2144 type2txt
[lsn
->type
]);
2145 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
2146 json_object_int_add(json
, "asn", lsn
->as_number
);
2147 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
2148 jsr
= json_object_new_object();
2149 json_object_object_add(json
, "segment-routing", jsr
);
2150 json_object_int_add(jsr
, "srgb-size", lsn
->srgb
.range_size
);
2151 json_object_int_add(jsr
, "srgb-lower", lsn
->srgb
.lower_bound
);
2152 jalgo
= json_object_new_array();
2153 json_object_object_add(jsr
, "algorithms", jalgo
);
2154 for (int i
= 0; i
< 2; i
++) {
2155 if (lsn
->algo
[i
] == 255)
2157 jobj
= json_object_new_object();
2159 snprintfrr(buf
, 2, "%u", i
);
2160 json_object_string_add(
2161 jobj
, buf
, lsn
->algo
[i
] == 0 ? "SPF" : "S-SPF");
2162 json_object_array_add(jalgo
, jobj
);
2164 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
2165 json_object_int_add(jsr
, "srlb-size",
2166 lsn
->srlb
.range_size
);
2167 json_object_int_add(jsr
, "srlb-lower",
2168 lsn
->srlb
.lower_bound
);
2170 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
2171 json_object_int_add(jsr
, "msd", lsn
->msd
);
2175 void ls_show_vertex(struct ls_vertex
*vertex
, struct vty
*vty
,
2176 struct json_object
*json
, bool verbose
)
2179 ls_show_vertex_json(vertex
, json
);
2181 ls_show_vertex_vty(vertex
, vty
, verbose
);
2184 void ls_show_vertices(struct ls_ted
*ted
, struct vty
*vty
,
2185 struct json_object
*json
, bool verbose
)
2187 struct ls_vertex
*vertex
;
2188 json_object
*jnodes
, *jnode
;
2191 jnodes
= json_object_new_array();
2192 json_object_object_add(json
, "vertices", jnodes
);
2193 frr_each (vertices
, &ted
->vertices
, vertex
) {
2194 jnode
= json_object_new_object();
2195 ls_show_vertex(vertex
, NULL
, jnode
, verbose
);
2196 json_object_array_add(jnodes
, jnode
);
2199 frr_each (vertices
, &ted
->vertices
, vertex
)
2200 ls_show_vertex(vertex
, vty
, NULL
, verbose
);
2204 static const char *edge_key_to_text(struct ls_edge_key key
)
2206 #define FORMAT_BUF_COUNT 4
2207 static char buf_ring
[FORMAT_BUF_COUNT
][INET6_BUFSIZ
];
2208 static size_t cur_buf
= 0;
2211 rv
= buf_ring
[cur_buf
];
2212 cur_buf
= (cur_buf
+ 1) % FORMAT_BUF_COUNT
;
2214 switch (key
.family
) {
2216 snprintfrr(rv
, INET6_BUFSIZ
, "%pI4", &key
.k
.addr
);
2219 snprintfrr(rv
, INET6_BUFSIZ
, "%pI6", &key
.k
.addr6
);
2222 snprintfrr(rv
, INET6_BUFSIZ
, "%" PRIu64
, key
.k
.link_id
);
2225 snprintfrr(rv
, INET6_BUFSIZ
, "(Unknown)");
2232 static void ls_show_edge_vty(struct ls_edge
*edge
, struct vty
*vty
,
2235 char admin_group_buf
[ADMIN_GROUP_PRINT_MAX_SIZE
];
2236 struct ls_attributes
*attr
;
2238 char buf
[INET6_BUFSIZ
];
2241 attr
= edge
->attributes
;
2242 sbuf_init(&sbuf
, NULL
, 0);
2244 sbuf_push(&sbuf
, 2, "Edge (%s): ", edge_key_to_text(edge
->key
));
2245 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
2246 sbuf_push(&sbuf
, 0, "%pI4", &attr
->standard
.local
);
2247 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
2248 sbuf_push(&sbuf
, 0, "%pI6", &attr
->standard
.local6
);
2250 sbuf_push(&sbuf
, 0, "%u/%u", attr
->standard
.local_id
,
2251 attr
->standard
.remote_id
);
2252 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
2253 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
2254 sbuf_push(&sbuf
, 0, "\tMetric: %u", attr
->metric
);
2255 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[edge
->status
]);
2260 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[attr
->adv
.origin
]);
2261 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2262 sbuf_push(&sbuf
, 4, "Name: %s\n", attr
->name
);
2263 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2264 sbuf_push(&sbuf
, 4, "TE Metric: %u\n",
2265 attr
->standard
.te_metric
);
2266 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2267 sbuf_push(&sbuf
, 4, "Admin Group: 0x%x\n",
2268 attr
->standard
.admin_group
);
2269 if (CHECK_FLAG(attr
->flags
, LS_ATTR_EXT_ADM_GRP
) &&
2270 admin_group_nb_words(&attr
->ext_admin_group
) != 0) {
2272 sbuf_push(&sbuf
, indent
, "Ext Admin Group: %s\n",
2274 admin_group_buf
, ADMIN_GROUP_PRINT_MAX_SIZE
,
2275 indent
+ strlen("Ext Admin Group: "),
2276 &attr
->ext_admin_group
));
2277 if (admin_group_buf
[0] != '\0' &&
2278 (sbuf
.pos
+ strlen(admin_group_buf
) +
2279 SBUF_DEFAULT_SIZE
/ 2) < sbuf
.size
)
2280 sbuf_push(&sbuf
, indent
+ 2, "Bit positions: %s\n",
2283 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
2284 sbuf_push(&sbuf
, 4, "Local IPv4 address: %pI4\n",
2285 &attr
->standard
.local
);
2286 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
2287 sbuf_push(&sbuf
, 4, "Remote IPv4 address: %pI4\n",
2288 &attr
->standard
.remote
);
2289 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
2290 sbuf_push(&sbuf
, 4, "Local IPv6 address: %pI6\n",
2291 &attr
->standard
.local6
);
2292 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
2293 sbuf_push(&sbuf
, 4, "Remote IPv6 address: %pI6\n",
2294 &attr
->standard
.remote6
);
2295 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2296 sbuf_push(&sbuf
, 4, "Local Identifier: %u\n",
2297 attr
->standard
.local_id
);
2298 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2299 sbuf_push(&sbuf
, 4, "Remote Identifier: %u\n",
2300 attr
->standard
.remote_id
);
2301 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2302 sbuf_push(&sbuf
, 4, "Maximum Bandwidth: %g (Bytes/s)\n",
2303 attr
->standard
.max_bw
);
2304 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2306 "Maximum Reservable Bandwidth: %g (Bytes/s)\n",
2307 attr
->standard
.max_rsv_bw
);
2308 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2309 sbuf_push(&sbuf
, 4, "Unreserved Bandwidth per Class Type\n");
2310 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
+= 2)
2312 "[%d]: %g (Bytes/sec)\t[%d]: %g (Bytes/s)\n",
2313 i
, attr
->standard
.unrsv_bw
[i
], i
+ 1,
2314 attr
->standard
.unrsv_bw
[i
+ 1]);
2316 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2317 sbuf_push(&sbuf
, 4, "Remote AS: %u\n",
2318 attr
->standard
.remote_as
);
2319 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
2320 sbuf_push(&sbuf
, 4, "Remote ASBR IPv4 address: %pI4\n",
2321 &attr
->standard
.remote_addr
);
2322 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
2323 sbuf_push(&sbuf
, 4, "Remote ASBR IPv6 address: %pI6\n",
2324 &attr
->standard
.remote_addr6
);
2325 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2326 sbuf_push(&sbuf
, 4, "Average Link Delay: %d (micro-sec)\n",
2327 attr
->extended
.delay
);
2328 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
))
2329 sbuf_push(&sbuf
, 4, "Min/Max Link Delay: %d/%d (micro-sec)\n",
2330 attr
->extended
.min_delay
, attr
->extended
.max_delay
);
2331 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2332 sbuf_push(&sbuf
, 4, "Delay Variation: %d (micro-sec)\n",
2333 attr
->extended
.jitter
);
2334 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2335 sbuf_push(&sbuf
, 4, "Link Loss: %g (%%)\n",
2336 (float)(attr
->extended
.pkt_loss
* LOSS_PRECISION
));
2337 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2338 sbuf_push(&sbuf
, 4, "Available Bandwidth: %g (Bytes/s)\n",
2339 attr
->extended
.ava_bw
);
2340 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2341 sbuf_push(&sbuf
, 4, "Residual Bandwidth: %g (Bytes/s)\n",
2342 attr
->extended
.rsv_bw
);
2343 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2344 sbuf_push(&sbuf
, 4, "Utilized Bandwidth: %g (Bytes/s)\n",
2345 attr
->extended
.used_bw
);
2346 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2347 sbuf_push(&sbuf
, 4, "IPv4 Adjacency-SID: %u",
2348 attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
2349 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2350 attr
->adj_sid
[ADJ_PRI_IPV4
].flags
,
2351 attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
2353 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2354 sbuf_push(&sbuf
, 4, "IPv4 Bck. Adjacency-SID: %u",
2355 attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
2356 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2357 attr
->adj_sid
[ADJ_BCK_IPV4
].flags
,
2358 attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
2360 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
2361 sbuf_push(&sbuf
, 4, "IPv6 Adjacency-SID: %u",
2362 attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
2363 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2364 attr
->adj_sid
[ADJ_PRI_IPV6
].flags
,
2365 attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
2367 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
2368 sbuf_push(&sbuf
, 4, "IPv6 Bck. Adjacency-SID: %u",
2369 attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
2370 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2371 attr
->adj_sid
[ADJ_BCK_IPV6
].flags
,
2372 attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
2374 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2375 sbuf_push(&sbuf
, 4, "SRLGs: %d", attr
->srlg_len
);
2376 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2378 sbuf_push(&sbuf
, 8, "\n%u", attr
->srlgs
[i
]);
2380 sbuf_push(&sbuf
, 8, ", %u", attr
->srlgs
[i
]);
2382 sbuf_push(&sbuf
, 0, "\n");
2386 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2390 static void ls_show_edge_json(struct ls_edge
*edge
, struct json_object
*json
)
2392 struct ls_attributes
*attr
;
2393 struct json_object
*jte
, *jbw
, *jobj
, *jsr
= NULL
, *jsrlg
, *js_ext_ag
,
2394 *js_ext_ag_arr_word
,
2396 char buf
[INET6_BUFSIZ
];
2397 char buf_ag
[strlen("0xffffffff") + 1];
2401 attr
= edge
->attributes
;
2403 json_object_string_add(json
, "edge-id", edge_key_to_text(edge
->key
));
2404 json_object_string_add(json
, "status", status2txt
[edge
->status
]);
2405 json_object_string_add(json
, "origin", origin2txt
[attr
->adv
.origin
]);
2406 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
2407 json_object_string_add(json
, "advertised-router", buf
);
2409 json_object_int_add(json
, "local-vertex-id", edge
->source
->key
);
2410 if (edge
->destination
)
2411 json_object_int_add(json
, "remote-vertex-id",
2412 edge
->destination
->key
);
2413 json_object_int_add(json
, "metric", attr
->metric
);
2414 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2415 json_object_string_add(json
, "name", attr
->name
);
2416 jte
= json_object_new_object();
2417 json_object_object_add(json
, "edge-attributes", jte
);
2418 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2419 json_object_int_add(jte
, "te-metric", attr
->standard
.te_metric
);
2420 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2421 json_object_int_add(jte
, "admin-group",
2422 attr
->standard
.admin_group
);
2423 if (CHECK_FLAG(attr
->flags
, LS_ATTR_EXT_ADM_GRP
)) {
2424 js_ext_ag
= json_object_new_object();
2425 json_object_object_add(jte
, "extAdminGroup", js_ext_ag
);
2426 js_ext_ag_arr_word
= json_object_new_array();
2427 json_object_object_add(js_ext_ag
, "words", js_ext_ag_arr_word
);
2428 js_ext_ag_arr_bit
= json_object_new_array();
2429 json_object_object_add(js_ext_ag
, "bitPositions",
2431 for (i
= 0; i
< admin_group_nb_words(&attr
->ext_admin_group
);
2433 bitmap
= admin_group_get_offset(&attr
->ext_admin_group
,
2435 snprintf(buf_ag
, sizeof(buf_ag
), "0x%08x", bitmap
);
2436 json_object_array_add(js_ext_ag_arr_word
,
2437 json_object_new_string(buf_ag
));
2440 i
< (admin_group_size(&attr
->ext_admin_group
) * WORD_SIZE
);
2442 if (admin_group_get(&attr
->ext_admin_group
, i
))
2443 json_object_array_add(js_ext_ag_arr_bit
,
2444 json_object_new_int(i
));
2447 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)) {
2448 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.local
);
2449 json_object_string_add(jte
, "local-address", buf
);
2451 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
)) {
2452 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.remote
);
2453 json_object_string_add(jte
, "remote-address", buf
);
2455 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)) {
2456 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.local6
);
2457 json_object_string_add(jte
, "local-address-v6", buf
);
2459 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
)) {
2460 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.remote6
);
2461 json_object_string_add(jte
, "remote-address-v6", buf
);
2463 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2464 json_object_int_add(jte
, "local-identifier",
2465 attr
->standard
.local_id
);
2466 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2467 json_object_int_add(jte
, "remote-identifier",
2468 attr
->standard
.remote_id
);
2469 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2470 json_object_double_add(jte
, "max-link-bandwidth",
2471 attr
->standard
.max_bw
);
2472 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2473 json_object_double_add(jte
, "max-resv-link-bandwidth",
2474 attr
->standard
.max_rsv_bw
);
2475 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2476 jbw
= json_object_new_array();
2477 json_object_object_add(jte
, "unreserved-bandwidth", jbw
);
2478 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
++) {
2479 jobj
= json_object_new_object();
2480 snprintfrr(buf
, 13, "class-type-%u", i
);
2481 json_object_double_add(jobj
, buf
,
2482 attr
->standard
.unrsv_bw
[i
]);
2483 json_object_array_add(jbw
, jobj
);
2486 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2487 json_object_int_add(jte
, "remote-asn",
2488 attr
->standard
.remote_as
);
2489 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
)) {
2490 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4",
2491 &attr
->standard
.remote_addr
);
2492 json_object_string_add(jte
, "remote-as-address", buf
);
2494 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
)) {
2495 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6",
2496 &attr
->standard
.remote_addr6
);
2497 json_object_string_add(jte
, "remote-as-address-v6", buf
);
2499 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2500 json_object_int_add(jte
, "delay", attr
->extended
.delay
);
2501 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
2502 json_object_int_add(jte
, "min-delay", attr
->extended
.min_delay
);
2503 json_object_int_add(jte
, "max-delay", attr
->extended
.max_delay
);
2505 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2506 json_object_int_add(jte
, "jitter", attr
->extended
.jitter
);
2507 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2508 json_object_double_add(
2509 jte
, "loss", attr
->extended
.pkt_loss
* LOSS_PRECISION
);
2510 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2511 json_object_double_add(jte
, "available-bandwidth",
2512 attr
->extended
.ava_bw
);
2513 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2514 json_object_double_add(jte
, "residual-bandwidth",
2515 attr
->extended
.rsv_bw
);
2516 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2517 json_object_double_add(jte
, "utilized-bandwidth",
2518 attr
->extended
.used_bw
);
2519 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2520 jsrlg
= json_object_new_array();
2521 json_object_object_add(jte
, "srlgs", jsrlg
);
2522 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2523 jobj
= json_object_new_object();
2524 json_object_int_add(jobj
, "srlg", attr
->srlgs
[i
]);
2525 json_object_array_add(jsrlg
, jobj
);
2528 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2529 jsr
= json_object_new_array();
2530 json_object_object_add(json
, "segment-routing", jsr
);
2531 jobj
= json_object_new_object();
2532 json_object_int_add(jobj
, "adj-sid",
2533 attr
->adj_sid
[ADJ_PRI_IPV4
].sid
);
2534 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_PRI_IPV4
].flags
);
2535 json_object_string_add(jobj
, "flags", buf
);
2536 json_object_int_add(jobj
, "weight",
2537 attr
->adj_sid
[ADJ_PRI_IPV4
].weight
);
2538 json_object_array_add(jsr
, jobj
);
2540 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2542 jsr
= json_object_new_array();
2543 json_object_object_add(json
, "segment-routing", jsr
);
2545 jobj
= json_object_new_object();
2546 json_object_int_add(jobj
, "adj-sid",
2547 attr
->adj_sid
[ADJ_BCK_IPV4
].sid
);
2548 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_BCK_IPV4
].flags
);
2549 json_object_string_add(jobj
, "flags", buf
);
2550 json_object_int_add(jobj
, "weight",
2551 attr
->adj_sid
[ADJ_BCK_IPV4
].weight
);
2552 json_object_array_add(jsr
, jobj
);
2554 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID6
)) {
2555 jsr
= json_object_new_array();
2556 json_object_object_add(json
, "segment-routing", jsr
);
2557 jobj
= json_object_new_object();
2558 json_object_int_add(jobj
, "adj-sid",
2559 attr
->adj_sid
[ADJ_PRI_IPV6
].sid
);
2560 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_PRI_IPV6
].flags
);
2561 json_object_string_add(jobj
, "flags", buf
);
2562 json_object_int_add(jobj
, "weight",
2563 attr
->adj_sid
[ADJ_PRI_IPV6
].weight
);
2564 json_object_array_add(jsr
, jobj
);
2566 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID6
)) {
2568 jsr
= json_object_new_array();
2569 json_object_object_add(json
, "segment-routing", jsr
);
2571 jobj
= json_object_new_object();
2572 json_object_int_add(jobj
, "adj-sid",
2573 attr
->adj_sid
[ADJ_BCK_IPV6
].sid
);
2574 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[ADJ_BCK_IPV6
].flags
);
2575 json_object_string_add(jobj
, "flags", buf
);
2576 json_object_int_add(jobj
, "weight",
2577 attr
->adj_sid
[ADJ_BCK_IPV6
].weight
);
2578 json_object_array_add(jsr
, jobj
);
2582 void ls_show_edge(struct ls_edge
*edge
, struct vty
*vty
,
2583 struct json_object
*json
, bool verbose
)
2590 ls_show_edge_json(edge
, json
);
2592 ls_show_edge_vty(edge
, vty
, verbose
);
2595 void ls_show_edges(struct ls_ted
*ted
, struct vty
*vty
,
2596 struct json_object
*json
, bool verbose
)
2598 struct ls_edge
*edge
;
2599 json_object
*jedges
, *jedge
;
2602 jedges
= json_object_new_array();
2603 json_object_object_add(json
, "edges", jedges
);
2604 frr_each (edges
, &ted
->edges
, edge
) {
2605 jedge
= json_object_new_object();
2606 ls_show_edge(edge
, NULL
, jedge
, verbose
);
2607 json_object_array_add(jedges
, jedge
);
2610 frr_each (edges
, &ted
->edges
, edge
)
2611 ls_show_edge(edge
, vty
, NULL
, verbose
);
2615 static void ls_show_subnet_vty(struct ls_subnet
*subnet
, struct vty
*vty
,
2618 struct ls_prefix
*pref
;
2620 char buf
[INET6_BUFSIZ
];
2622 pref
= subnet
->ls_pref
;
2623 sbuf_init(&sbuf
, NULL
, 0);
2625 sbuf_push(&sbuf
, 2, "Subnet: %pFX", &subnet
->key
);
2626 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2627 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
2628 sbuf_push(&sbuf
, 0, "\tMetric: %d", pref
->metric
);
2629 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[subnet
->status
]);
2634 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[pref
->adv
.origin
]);
2635 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
))
2636 sbuf_push(&sbuf
, 4, "Flags: %d\n", pref
->igp_flag
);
2638 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2639 sbuf_push(&sbuf
, 4, "Tag: %d\n", pref
->route_tag
);
2641 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2642 sbuf_push(&sbuf
, 4, "Extended Tag: %" PRIu64
"\n",
2643 pref
->extended_tag
);
2645 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
))
2646 sbuf_push(&sbuf
, 4, "SID: %d\tAlgorithm: %d\tFlags: 0x%x\n",
2647 pref
->sr
.sid
, pref
->sr
.algo
, pref
->sr
.sid_flag
);
2650 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2654 static void ls_show_subnet_json(struct ls_subnet
*subnet
,
2655 struct json_object
*json
)
2657 struct ls_prefix
*pref
;
2659 char buf
[INET6_BUFSIZ
];
2661 pref
= subnet
->ls_pref
;
2663 snprintfrr(buf
, INET6_BUFSIZ
, "%pFX", &subnet
->key
);
2664 json_object_string_add(json
, "subnet-id", buf
);
2665 json_object_string_add(json
, "status", status2txt
[subnet
->status
]);
2666 json_object_string_add(json
, "origin", origin2txt
[pref
->adv
.origin
]);
2667 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2668 json_object_string_add(json
, "advertised-router", buf
);
2670 json_object_int_add(json
, "vertex-id", subnet
->vertex
->key
);
2671 json_object_int_add(json
, "metric", pref
->metric
);
2672 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
)) {
2673 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->igp_flag
);
2674 json_object_string_add(json
, "flags", buf
);
2676 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2677 json_object_int_add(json
, "tag", pref
->route_tag
);
2678 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2679 json_object_int_add(json
, "extended-tag", pref
->extended_tag
);
2680 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
)) {
2681 jsr
= json_object_new_object();
2682 json_object_object_add(json
, "segment-routing", jsr
);
2683 json_object_int_add(jsr
, "pref-sid", pref
->sr
.sid
);
2684 json_object_int_add(jsr
, "algo", pref
->sr
.algo
);
2685 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->sr
.sid_flag
);
2686 json_object_string_add(jsr
, "flags", buf
);
2690 void ls_show_subnet(struct ls_subnet
*subnet
, struct vty
*vty
,
2691 struct json_object
*json
, bool verbose
)
2698 ls_show_subnet_json(subnet
, json
);
2700 ls_show_subnet_vty(subnet
, vty
, verbose
);
2703 void ls_show_subnets(struct ls_ted
*ted
, struct vty
*vty
,
2704 struct json_object
*json
, bool verbose
)
2706 struct ls_subnet
*subnet
;
2707 json_object
*jsubs
, *jsub
;
2710 jsubs
= json_object_new_array();
2711 json_object_object_add(json
, "subnets", jsubs
);
2712 frr_each (subnets
, &ted
->subnets
, subnet
) {
2713 jsub
= json_object_new_object();
2714 ls_show_subnet(subnet
, NULL
, jsub
, verbose
);
2715 json_object_array_add(jsubs
, jsub
);
2718 frr_each (subnets
, &ted
->subnets
, subnet
)
2719 ls_show_subnet(subnet
, vty
, NULL
, verbose
);
2723 void ls_show_ted(struct ls_ted
*ted
, struct vty
*vty
, struct json_object
*json
,
2729 jted
= json_object_new_object();
2730 json_object_object_add(json
, "ted", jted
);
2731 json_object_string_add(jted
, "name", ted
->name
);
2732 json_object_int_add(jted
, "key", ted
->key
);
2733 json_object_int_add(jted
, "verticesCount",
2734 vertices_count(&ted
->vertices
));
2735 json_object_int_add(jted
, "edgesCount",
2736 edges_count(&ted
->edges
));
2737 json_object_int_add(jted
, "subnetsCount",
2738 subnets_count(&ted
->subnets
));
2739 ls_show_vertices(ted
, NULL
, jted
, verbose
);
2740 ls_show_edges(ted
, NULL
, jted
, verbose
);
2741 ls_show_subnets(ted
, NULL
, jted
, verbose
);
2747 "\n\tTraffic Engineering Database: %s (key: %d)\n\n",
2748 ted
->name
, ted
->key
);
2749 ls_show_vertices(ted
, vty
, NULL
, verbose
);
2750 ls_show_edges(ted
, vty
, NULL
, verbose
);
2751 ls_show_subnets(ted
, vty
, NULL
, verbose
);
2753 "\n\tTotal: %zu Vertices, %zu Edges, %zu Subnets\n\n",
2754 vertices_count(&ted
->vertices
),
2755 edges_count(&ted
->edges
), subnets_count(&ted
->subnets
));
2759 void ls_dump_ted(struct ls_ted
*ted
)
2761 struct ls_vertex
*vertex
;
2762 struct ls_edge
*edge
;
2763 struct ls_subnet
*subnet
;
2764 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
2766 zlog_debug("(%s) Ted init", __func__
);
2768 /* Loop TED, start printing Node, then Attributes and finally Prefix */
2769 frr_each (vertices
, &ted
->vertices
, vertex
) {
2770 zlog_debug(" Ted node (%s %pI4 %s)",
2771 vertex
->node
->name
[0] ? vertex
->node
->name
2773 &vertex
->node
->router_id
,
2774 origin2txt
[vertex
->node
->adv
.origin
]);
2775 struct listnode
*lst_node
;
2776 struct ls_edge
*vertex_edge
;
2778 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, lst_node
,
2781 " inc edge key:%s attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2782 edge_key_to_text(vertex_edge
->key
),
2783 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2784 &vertex_edge
->attributes
->standard
.local
,
2785 &vertex_edge
->attributes
->standard
.remote
);
2787 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, lst_node
,
2790 " out edge key:%s attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2791 edge_key_to_text(vertex_edge
->key
),
2792 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2793 &vertex_edge
->attributes
->standard
.local
,
2794 &vertex_edge
->attributes
->standard
.remote
);
2797 frr_each (edges
, &ted
->edges
, edge
) {
2798 zlog_debug(" Ted edge key:%s src:%pI4 dst:%pI4",
2799 edge_key_to_text(edge
->key
),
2800 edge
->source
? &edge
->source
->node
->router_id
2803 ? &edge
->destination
->node
->router_id
2806 frr_each (subnets
, &ted
->subnets
, subnet
) {
2807 zlog_debug(" Ted subnet key:%pFX vertex:%pI4",
2808 &subnet
->ls_pref
->pref
,
2809 &subnet
->vertex
->node
->adv
.id
.ip
.addr
);
2811 zlog_debug("(%s) Ted end", __func__
);