]>
git.proxmox.com Git - mirror_frr.git/blob - lib/link_state.c
2 * Link State Database - link_state.c
4 * Author: Olivier Dugeon <olivier.dugeon@orange.com>
6 * Copyright (C) 2020 Orange http://www.orange.com
8 * This file is part of Free Range Routing (FRR).
10 * FRR is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2, or (at your option) any
15 * FRR is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with this program; see the file COPYING; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 #include "termtable.h"
41 #include "link_state.h"
43 /* Link State Memory allocation */
44 DEFINE_MTYPE_STATIC(LIB
, LS_DB
, "Link State Database");
47 * Link State Node management functions
49 int ls_node_id_same(struct ls_node_id i1
, struct ls_node_id i2
)
51 if (i1
.origin
!= i2
.origin
)
54 if (i1
.origin
== UNKNOWN
)
57 if (i1
.origin
== ISIS_L1
|| i1
.origin
== ISIS_L2
) {
58 if (memcmp(i1
.id
.iso
.sys_id
, i2
.id
.iso
.sys_id
, ISO_SYS_ID_LEN
)
60 || (i1
.id
.iso
.level
!= i2
.id
.iso
.level
))
63 if (!IPV4_ADDR_SAME(&i1
.id
.ip
.addr
, &i2
.id
.ip
.addr
)
64 || !IPV4_ADDR_SAME(&i1
.id
.ip
.area_id
, &i2
.id
.ip
.area_id
))
71 struct ls_node
*ls_node_new(struct ls_node_id adv
, struct in_addr rid
,
76 if (adv
.origin
== UNKNOWN
)
79 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
81 if (!IPV4_NET0(rid
.s_addr
)) {
83 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID
);
85 if (adv
.origin
== OSPFv2
|| adv
.origin
== STATIC
86 || adv
.origin
== DIRECT
) {
87 new->router_id
= adv
.id
.ip
.addr
;
88 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID
);
91 if (!IN6_IS_ADDR_UNSPECIFIED(&rid6
)) {
92 new->router6_id
= rid6
;
93 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID6
);
98 void ls_node_del(struct ls_node
*node
)
103 XFREE(MTYPE_LS_DB
, node
);
106 int ls_node_same(struct ls_node
*n1
, struct ls_node
*n2
)
108 /* First, check pointer */
109 if ((n1
&& !n2
) || (!n1
&& n2
))
115 /* Then, verify Flags and Origin */
116 if (n1
->flags
!= n2
->flags
)
119 if (!ls_node_id_same(n1
->adv
, n2
->adv
))
122 /* Finally, check each individual parameters that are valid */
123 if (CHECK_FLAG(n1
->flags
, LS_NODE_NAME
)
124 && (strncmp(n1
->name
, n2
->name
, MAX_NAME_LENGTH
) != 0))
126 if (CHECK_FLAG(n1
->flags
, LS_NODE_ROUTER_ID
)
127 && !IPV4_ADDR_SAME(&n1
->router_id
, &n2
->router_id
))
129 if (CHECK_FLAG(n1
->flags
, LS_NODE_ROUTER_ID6
)
130 && !IPV6_ADDR_SAME(&n1
->router6_id
, &n2
->router6_id
))
132 if (CHECK_FLAG(n1
->flags
, LS_NODE_FLAG
)
133 && (n1
->node_flag
!= n2
->node_flag
))
135 if (CHECK_FLAG(n1
->flags
, LS_NODE_TYPE
) && (n1
->type
!= n2
->type
))
137 if (CHECK_FLAG(n1
->flags
, LS_NODE_AS_NUMBER
)
138 && (n1
->as_number
!= n2
->as_number
))
140 if (CHECK_FLAG(n1
->flags
, LS_NODE_SR
)) {
141 if (n1
->srgb
.flag
!= n2
->srgb
.flag
142 || n1
->srgb
.lower_bound
!= n2
->srgb
.lower_bound
143 || n1
->srgb
.range_size
!= n2
->srgb
.range_size
)
145 if ((n1
->algo
[0] != n2
->algo
[0])
146 || (n1
->algo
[1] != n2
->algo
[1]))
148 if (CHECK_FLAG(n1
->flags
, LS_NODE_SRLB
)
149 && ((n1
->srlb
.lower_bound
!= n2
->srlb
.lower_bound
150 || n1
->srlb
.range_size
!= n2
->srlb
.range_size
)))
152 if (CHECK_FLAG(n1
->flags
, LS_NODE_MSD
) && (n1
->msd
!= n2
->msd
))
156 /* OK, n1 & n2 are equal */
161 * Link State Attributes management functions
163 struct ls_attributes
*ls_attributes_new(struct ls_node_id adv
,
164 struct in_addr local
,
165 struct in6_addr local6
,
168 struct ls_attributes
*new;
170 if (adv
.origin
== UNKNOWN
)
173 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
175 if (!IPV4_NET0(local
.s_addr
)) {
176 new->standard
.local
= local
;
177 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
);
179 if (!IN6_IS_ADDR_UNSPECIFIED(&local6
)) {
180 new->standard
.local6
= local6
;
181 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR6
);
184 new->standard
.local_id
= local_id
;
185 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ID
);
188 /* Check that almost one identifier is set */
189 if (!CHECK_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
| LS_ATTR_LOCAL_ADDR6
190 | LS_ATTR_LOCAL_ID
)) {
191 XFREE(MTYPE_LS_DB
, new);
198 void ls_attributes_srlg_del(struct ls_attributes
*attr
)
204 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
208 UNSET_FLAG(attr
->flags
, LS_ATTR_SRLG
);
211 void ls_attributes_del(struct ls_attributes
*attr
)
216 ls_attributes_srlg_del(attr
);
218 XFREE(MTYPE_LS_DB
, attr
);
221 int ls_attributes_same(struct ls_attributes
*l1
, struct ls_attributes
*l2
)
223 /* First, check pointer */
224 if ((l1
&& !l2
) || (!l1
&& l2
))
230 /* Then, verify Flags and Origin */
231 if (l1
->flags
!= l2
->flags
)
234 if (!ls_node_id_same(l1
->adv
, l2
->adv
))
237 /* Finally, check each individual parameters that are valid */
238 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NAME
)
239 && strncmp(l1
->name
, l2
->name
, MAX_NAME_LENGTH
) != 0)
241 if (CHECK_FLAG(l1
->flags
, LS_ATTR_METRIC
) && (l1
->metric
!= l2
->metric
))
243 if (CHECK_FLAG(l1
->flags
, LS_ATTR_TE_METRIC
)
244 && (l1
->standard
.te_metric
!= l2
->standard
.te_metric
))
246 if (CHECK_FLAG(l1
->flags
, LS_ATTR_ADM_GRP
)
247 && (l1
->standard
.admin_group
!= l2
->standard
.admin_group
))
249 if (CHECK_FLAG(l1
->flags
, LS_ATTR_LOCAL_ADDR
)
250 && !IPV4_ADDR_SAME(&l1
->standard
.local
, &l2
->standard
.local
))
252 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NEIGH_ADDR
)
253 && !IPV4_ADDR_SAME(&l1
->standard
.remote
, &l2
->standard
.remote
))
255 if (CHECK_FLAG(l1
->flags
, LS_ATTR_LOCAL_ADDR6
)
256 && !IPV6_ADDR_SAME(&l1
->standard
.local6
, &l2
->standard
.local6
))
258 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NEIGH_ADDR6
)
259 && !IPV6_ADDR_SAME(&l1
->standard
.remote6
, &l2
->standard
.remote6
))
261 if (CHECK_FLAG(l1
->flags
, LS_ATTR_LOCAL_ID
)
262 && (l1
->standard
.local_id
!= l2
->standard
.local_id
))
264 if (CHECK_FLAG(l1
->flags
, LS_ATTR_NEIGH_ID
)
265 && (l1
->standard
.remote_id
!= l2
->standard
.remote_id
))
267 if (CHECK_FLAG(l1
->flags
, LS_ATTR_MAX_BW
)
268 && (l1
->standard
.max_bw
!= l2
->standard
.max_bw
))
270 if (CHECK_FLAG(l1
->flags
, LS_ATTR_MAX_RSV_BW
)
271 && (l1
->standard
.max_rsv_bw
!= l2
->standard
.max_rsv_bw
))
273 if (CHECK_FLAG(l1
->flags
, LS_ATTR_UNRSV_BW
)
274 && memcmp(&l1
->standard
.unrsv_bw
, &l2
->standard
.unrsv_bw
, 32) != 0)
276 if (CHECK_FLAG(l1
->flags
, LS_ATTR_REMOTE_AS
)
277 && (l1
->standard
.remote_as
!= l2
->standard
.remote_as
))
279 if (CHECK_FLAG(l1
->flags
, LS_ATTR_REMOTE_ADDR
)
280 && !IPV4_ADDR_SAME(&l1
->standard
.remote_addr
,
281 &l2
->standard
.remote_addr
))
283 if (CHECK_FLAG(l1
->flags
, LS_ATTR_REMOTE_ADDR6
)
284 && !IPV6_ADDR_SAME(&l1
->standard
.remote_addr6
,
285 &l2
->standard
.remote_addr6
))
287 if (CHECK_FLAG(l1
->flags
, LS_ATTR_DELAY
)
288 && (l1
->extended
.delay
!= l2
->extended
.delay
))
290 if (CHECK_FLAG(l1
->flags
, LS_ATTR_MIN_MAX_DELAY
)
291 && ((l1
->extended
.min_delay
!= l2
->extended
.min_delay
)
292 || (l1
->extended
.max_delay
!= l2
->extended
.max_delay
)))
294 if (CHECK_FLAG(l1
->flags
, LS_ATTR_JITTER
)
295 && (l1
->extended
.jitter
!= l2
->extended
.jitter
))
297 if (CHECK_FLAG(l1
->flags
, LS_ATTR_PACKET_LOSS
)
298 && (l1
->extended
.pkt_loss
!= l2
->extended
.pkt_loss
))
300 if (CHECK_FLAG(l1
->flags
, LS_ATTR_AVA_BW
)
301 && (l1
->extended
.ava_bw
!= l2
->extended
.ava_bw
))
303 if (CHECK_FLAG(l1
->flags
, LS_ATTR_RSV_BW
)
304 && (l1
->extended
.rsv_bw
!= l2
->extended
.rsv_bw
))
306 if (CHECK_FLAG(l1
->flags
, LS_ATTR_USE_BW
)
307 && (l1
->extended
.used_bw
!= l2
->extended
.used_bw
))
309 if (CHECK_FLAG(l1
->flags
, LS_ATTR_ADJ_SID
)) {
310 if ((l1
->adj_sid
[0].sid
!= l2
->adj_sid
[0].sid
)
311 || (l1
->adj_sid
[0].flags
!= l2
->adj_sid
[0].flags
)
312 || (l1
->adj_sid
[0].weight
!= l2
->adj_sid
[0].weight
))
314 if (((l1
->adv
.origin
== ISIS_L1
) || (l1
->adv
.origin
== ISIS_L2
))
315 && (memcmp(&l1
->adj_sid
[0].neighbor
.sysid
,
316 &l2
->adj_sid
[0].neighbor
.sysid
, ISO_SYS_ID_LEN
)
319 if (((l1
->adv
.origin
== OSPFv2
) || (l1
->adv
.origin
== STATIC
)
320 || (l1
->adv
.origin
== DIRECT
))
321 && (!IPV4_ADDR_SAME(&l1
->adj_sid
[0].neighbor
.addr
,
322 &l2
->adj_sid
[0].neighbor
.addr
)))
325 if (CHECK_FLAG(l1
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
326 if ((l1
->adj_sid
[1].sid
!= l2
->adj_sid
[1].sid
)
327 || (l1
->adj_sid
[1].flags
!= l2
->adj_sid
[1].flags
)
328 || (l1
->adj_sid
[1].weight
!= l2
->adj_sid
[1].weight
))
330 if (((l1
->adv
.origin
== ISIS_L1
) || (l1
->adv
.origin
== ISIS_L2
))
331 && (memcmp(&l1
->adj_sid
[1].neighbor
.sysid
,
332 &l2
->adj_sid
[1].neighbor
.sysid
, ISO_SYS_ID_LEN
)
335 if (((l1
->adv
.origin
== OSPFv2
) || (l1
->adv
.origin
== STATIC
)
336 || (l1
->adv
.origin
== DIRECT
))
337 && (!IPV4_ADDR_SAME(&l1
->adj_sid
[1].neighbor
.addr
,
338 &l2
->adj_sid
[1].neighbor
.addr
)))
341 if (CHECK_FLAG(l1
->flags
, LS_ATTR_SRLG
)
342 && ((l1
->srlg_len
!= l2
->srlg_len
)
343 || memcmp(l1
->srlgs
, l2
->srlgs
,
344 l1
->srlg_len
* sizeof(uint32_t))
348 /* OK, l1 & l2 are equal */
353 * Link State prefix management functions
355 struct ls_prefix
*ls_prefix_new(struct ls_node_id adv
, struct prefix p
)
357 struct ls_prefix
*new;
359 if (adv
.origin
== UNKNOWN
)
362 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
369 void ls_prefix_del(struct ls_prefix
*pref
)
374 XFREE(MTYPE_LS_DB
, pref
);
377 int ls_prefix_same(struct ls_prefix
*p1
, struct ls_prefix
*p2
)
379 /* First, check pointer */
380 if ((p1
&& !p2
) || (!p1
&& p2
))
386 /* Then, verify Flags and Origin */
387 if (p1
->flags
!= p2
->flags
)
390 if (!ls_node_id_same(p1
->adv
, p2
->adv
))
393 /* Finally, check each individual parameters that are valid */
394 if (prefix_same(&p1
->pref
, &p2
->pref
) == 0)
396 if (CHECK_FLAG(p1
->flags
, LS_PREF_IGP_FLAG
)
397 && (p1
->igp_flag
!= p2
->igp_flag
))
399 if (CHECK_FLAG(p1
->flags
, LS_PREF_ROUTE_TAG
)
400 && (p1
->route_tag
!= p2
->route_tag
))
402 if (CHECK_FLAG(p1
->flags
, LS_PREF_EXTENDED_TAG
)
403 && (p1
->extended_tag
!= p2
->extended_tag
))
405 if (CHECK_FLAG(p1
->flags
, LS_PREF_METRIC
) && (p1
->metric
!= p2
->metric
))
407 if (CHECK_FLAG(p1
->flags
, LS_PREF_SR
)) {
408 if ((p1
->sr
.algo
!= p2
->sr
.algo
) || (p1
->sr
.sid
!= p2
->sr
.sid
)
409 || (p1
->sr
.sid_flag
!= p2
->sr
.sid_flag
))
413 /* OK, p1 & p2 are equal */
418 * Link State Vertices management functions
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 memcpy(&key
, &node
->adv
.id
.iso
.sys_id
, ISO_SYS_ID_LEN
);
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 memcpy(&vertex
.key
, &nid
.id
.iso
.sys_id
, ISO_SYS_ID_LEN
);
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 struct ls_edge
*ls_edge_add(struct ls_ted
*ted
,
677 struct ls_attributes
*attributes
)
682 if (attributes
== NULL
)
685 /* Key is the IPv4 local address */
686 if (!IPV4_NET0(attributes
->standard
.local
.s_addr
))
687 key
= ((uint64_t)ntohl(attributes
->standard
.local
.s_addr
))
689 /* or the IPv6 local address if IPv4 is not defined */
690 else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes
->standard
.local6
))
691 key
= (uint64_t)(attributes
->standard
.local6
.s6_addr32
[0]
693 | ((uint64_t)attributes
->standard
.local6
.s6_addr32
[1]
695 /* of local identifier if no IP addresses are defined */
696 else if (attributes
->standard
.local_id
!= 0)
698 (attributes
->standard
.local_id
& 0xffffffff)
699 | ((uint64_t)attributes
->standard
.remote_id
<< 32));
701 /* Check that key is valid */
705 /* Create Edge and add it to the TED */
706 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_edge
));
708 new->attributes
= attributes
;
712 edges_add(&ted
->edges
, new);
714 /* Finally, connect Edge to Vertices */
715 ls_edge_connect_to(ted
, new);
720 struct ls_edge
*ls_find_edge_by_key(struct ls_ted
*ted
, const uint64_t key
)
722 struct ls_edge edge
= {};
728 return edges_find(&ted
->edges
, &edge
);
731 struct ls_edge
*ls_find_edge_by_source(struct ls_ted
*ted
,
732 struct ls_attributes
*attributes
)
734 struct ls_edge edge
= {};
736 if (attributes
== NULL
)
740 /* Key is the IPv4 local address */
741 if (!IPV4_NET0(attributes
->standard
.local
.s_addr
))
742 edge
.key
= ((uint64_t)ntohl(attributes
->standard
.local
.s_addr
))
744 /* or the IPv6 local address if IPv4 is not defined */
745 else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes
->standard
.local6
))
746 edge
.key
= (uint64_t)(attributes
->standard
.local6
.s6_addr32
[0]
748 | ((uint64_t)attributes
->standard
.local6
.s6_addr32
[1]
750 /* of local identifier if no IP addresses are defined */
751 else if (attributes
->standard
.local_id
!= 0)
752 edge
.key
= (uint64_t)(
753 (attributes
->standard
.local_id
& 0xffffffff)
754 | ((uint64_t)attributes
->standard
.remote_id
<< 32));
759 return edges_find(&ted
->edges
, &edge
);
762 struct ls_edge
*ls_find_edge_by_destination(struct ls_ted
*ted
,
763 struct ls_attributes
*attributes
)
765 struct ls_edge edge
= {};
767 if (attributes
== NULL
)
771 /* Key is the IPv4 remote address */
772 if (!IPV4_NET0(attributes
->standard
.remote
.s_addr
))
773 edge
.key
= ((uint64_t)ntohl(attributes
->standard
.remote
.s_addr
))
775 /* or the IPv6 remote address if IPv4 is not defined */
776 else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes
->standard
.remote6
))
778 (uint64_t)(attributes
->standard
.remote6
.s6_addr32
[0]
780 | ((uint64_t)attributes
->standard
.remote6
.s6_addr32
[1]
782 /* of remote identifier if no IP addresses are defined */
783 else if (attributes
->standard
.remote_id
!= 0)
784 edge
.key
= (uint64_t)(
785 (attributes
->standard
.remote_id
& 0xffffffff)
786 | ((uint64_t)attributes
->standard
.local_id
<< 32));
791 return edges_find(&ted
->edges
, &edge
);
794 struct ls_edge
*ls_edge_update(struct ls_ted
*ted
,
795 struct ls_attributes
*attributes
)
799 if (attributes
== NULL
)
802 /* First, search for an existing Edge */
803 old
= ls_find_edge_by_source(ted
, attributes
);
805 /* Check if attributes are similar */
806 if (!ls_attributes_same(old
->attributes
, attributes
)) {
807 ls_attributes_del(old
->attributes
);
808 old
->attributes
= attributes
;
810 old
->status
= UPDATE
;
814 /* If not found, add new Edge from the attributes */
815 return ls_edge_add(ted
, attributes
);
818 int ls_edge_same(struct ls_edge
*e1
, struct ls_edge
*e2
)
820 if ((e1
&& !e2
) || (!e1
&& e2
))
826 if (e1
->key
!= e2
->key
)
829 if (e1
->attributes
== e2
->attributes
)
832 return ls_attributes_same(e1
->attributes
, e2
->attributes
);
835 void ls_edge_del(struct ls_ted
*ted
, struct ls_edge
*edge
)
840 /* Fist disconnect Edge from Vertices */
841 ls_disconnect_edge(edge
);
842 /* Then remove it from the Data Base */
843 edges_del(&ted
->edges
, edge
);
844 XFREE(MTYPE_LS_DB
, edge
);
847 void ls_edge_del_all(struct ls_ted
*ted
, struct ls_edge
*edge
)
852 /* Remove associated Link State Attributes */
853 ls_attributes_del(edge
->attributes
);
854 /* Then Edge itself */
855 ls_edge_del(ted
, edge
);
859 * Link State Subnet Management functions.
861 struct ls_subnet
*ls_subnet_add(struct ls_ted
*ted
,
862 struct ls_prefix
*ls_pref
)
864 struct ls_subnet
*new;
865 struct ls_vertex
*vertex
;
866 struct ls_node
*node
;
867 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
872 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_subnet
));
873 new->ls_pref
= ls_pref
;
874 new->key
= ls_pref
->pref
;
879 vertex
= ls_find_vertex_by_id(ted
, ls_pref
->adv
);
880 if (vertex
== NULL
) {
881 /* Create a new temporary Node & Vertex if not found */
882 node
= ls_node_new(ls_pref
->adv
, inaddr_any
, in6addr_any
);
883 vertex
= ls_vertex_add(ted
, node
);
885 /* And attach the subnet to the corresponding Vertex */
886 new->vertex
= vertex
;
887 listnode_add_sort_nodup(vertex
->prefixes
, new);
889 subnets_add(&ted
->subnets
, new);
894 struct ls_subnet
*ls_subnet_update(struct ls_ted
*ted
, struct ls_prefix
*pref
)
896 struct ls_subnet
*old
;
901 old
= ls_find_subnet(ted
, pref
->pref
);
903 if (!ls_prefix_same(old
->ls_pref
, pref
)) {
904 ls_prefix_del(old
->ls_pref
);
907 old
->status
= UPDATE
;
911 return ls_subnet_add(ted
, pref
);
914 int ls_subnet_same(struct ls_subnet
*s1
, struct ls_subnet
*s2
)
916 if ((s1
&& !s2
) || (!s1
&& s2
))
922 if (!prefix_same(&s1
->key
, &s2
->key
))
925 if (s1
->ls_pref
== s2
->ls_pref
)
928 return ls_prefix_same(s1
->ls_pref
, s2
->ls_pref
);
931 void ls_subnet_del(struct ls_ted
*ted
, struct ls_subnet
*subnet
)
936 /* First, disconnect Subnet from associated Vertex */
937 listnode_delete(subnet
->vertex
->prefixes
, subnet
);
938 /* Then delete Subnet */
939 subnets_del(&ted
->subnets
, subnet
);
940 XFREE(MTYPE_LS_DB
, subnet
);
943 void ls_subnet_del_all(struct ls_ted
*ted
, struct ls_subnet
*subnet
)
948 /* First, remove associated Link State Subnet */
949 ls_prefix_del(subnet
->ls_pref
);
950 /* Then, delete Subnet itself */
951 ls_subnet_del(ted
, subnet
);
954 struct ls_subnet
*ls_find_subnet(struct ls_ted
*ted
, const struct prefix prefix
)
956 struct ls_subnet subnet
= {};
959 return subnets_find(&ted
->subnets
, &subnet
);
963 * Link State TED management functions
965 struct ls_ted
*ls_ted_new(const uint32_t key
, const char *name
,
970 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_ted
));
972 /* Set basic information for this ted */
974 new->as_number
= as_number
;
975 strlcpy(new->name
, name
, MAX_NAME_LENGTH
);
977 /* Initialize the various RB tree */
978 vertices_init(&new->vertices
);
979 edges_init(&new->edges
);
980 subnets_init(&new->subnets
);
985 void ls_ted_del(struct ls_ted
*ted
)
990 /* Check that TED is empty */
991 if (vertices_count(&ted
->vertices
) || edges_count(&ted
->edges
)
992 || subnets_count(&ted
->subnets
))
995 /* Release RB Tree */
996 vertices_fini(&ted
->vertices
);
997 edges_fini(&ted
->edges
);
998 subnets_fini(&ted
->subnets
);
1000 XFREE(MTYPE_LS_DB
, ted
);
1003 void ls_ted_del_all(struct ls_ted
*ted
)
1005 struct ls_vertex
*vertex
;
1006 struct ls_edge
*edge
;
1007 struct ls_subnet
*subnet
;
1012 /* First remove Vertices, Edges and Subnets and associated Link State */
1013 frr_each (vertices
, &ted
->vertices
, vertex
)
1014 ls_vertex_del_all(ted
, vertex
);
1015 frr_each (edges
, &ted
->edges
, edge
)
1016 ls_edge_del_all(ted
, edge
);
1017 frr_each (subnets
, &ted
->subnets
, subnet
)
1018 ls_subnet_del_all(ted
, subnet
);
1020 /* then remove TED itself */
1024 void ls_ted_clean(struct ls_ted
*ted
)
1026 struct ls_vertex
*vertex
;
1027 struct ls_edge
*edge
;
1028 struct ls_subnet
*subnet
;
1033 /* First, start with Vertices */
1034 frr_each (vertices
, &ted
->vertices
, vertex
)
1035 if (vertex
->status
== ORPHAN
)
1036 ls_vertex_del_all(ted
, vertex
);
1039 frr_each (edges
, &ted
->edges
, edge
)
1040 if (edge
->status
== ORPHAN
)
1041 ls_edge_del_all(ted
, edge
);
1044 frr_each (subnets
, &ted
->subnets
, subnet
)
1045 if (subnet
->status
== ORPHAN
)
1046 ls_subnet_del_all(ted
, subnet
);
1050 void ls_connect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
1052 if (vertex
== NULL
|| edge
== NULL
)
1056 listnode_add_sort_nodup(vertex
->outgoing_edges
, edge
);
1057 edge
->source
= vertex
;
1059 listnode_add_sort_nodup(vertex
->incoming_edges
, edge
);
1060 edge
->destination
= vertex
;
1064 void ls_disconnect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
1067 if (vertex
== NULL
|| edge
== NULL
)
1071 listnode_delete(vertex
->outgoing_edges
, edge
);
1072 edge
->source
= NULL
;
1074 listnode_delete(vertex
->incoming_edges
, edge
);
1075 edge
->destination
= NULL
;
1079 void ls_connect_vertices(struct ls_vertex
*src
, struct ls_vertex
*dst
,
1080 struct ls_edge
*edge
)
1086 edge
->destination
= dst
;
1089 listnode_add_sort_nodup(src
->outgoing_edges
, edge
);
1092 listnode_add_sort_nodup(dst
->incoming_edges
, edge
);
1095 void ls_disconnect_edge(struct ls_edge
*edge
)
1100 ls_disconnect(edge
->source
, edge
, true);
1101 ls_disconnect(edge
->destination
, edge
, false);
1103 /* Mark this Edge as ORPHAN for future cleanup */
1104 edge
->status
= ORPHAN
;
1108 * Link State Message management functions
1111 int ls_register(struct zclient
*zclient
, bool server
)
1116 rc
= zclient_register_opaque(zclient
, LINK_STATE_SYNC
);
1118 rc
= zclient_register_opaque(zclient
, LINK_STATE_UPDATE
);
1123 int ls_unregister(struct zclient
*zclient
, bool server
)
1128 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_SYNC
);
1130 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_UPDATE
);
1135 int ls_request_sync(struct zclient
*zclient
)
1140 /* Check buffer size */
1141 if (STREAM_SIZE(zclient
->obuf
)
1142 < (ZEBRA_HEADER_SIZE
+ 3 * sizeof(uint32_t)))
1148 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
1150 /* Set type and flags */
1151 stream_putl(s
, LINK_STATE_SYNC
);
1152 stream_putw(s
, flags
);
1153 /* Send destination client info */
1154 stream_putc(s
, zclient
->redist_default
);
1155 stream_putw(s
, zclient
->instance
);
1156 stream_putl(s
, zclient
->session_id
);
1158 /* Put length into the header at the start of the stream. */
1159 stream_putw_at(s
, 0, stream_get_endp(s
));
1161 return zclient_send_message(zclient
);
1164 static struct ls_node
*ls_parse_node(struct stream
*s
)
1166 struct ls_node
*node
;
1169 node
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
1171 STREAM_GET(&node
->adv
, s
, sizeof(struct ls_node_id
));
1172 STREAM_GETW(s
, node
->flags
);
1173 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1174 STREAM_GETC(s
, len
);
1175 STREAM_GET(node
->name
, s
, len
);
1177 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1178 node
->router_id
.s_addr
= stream_get_ipv4(s
);
1179 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1180 STREAM_GET(&node
->router6_id
, s
, IPV6_MAX_BYTELEN
);
1181 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1182 STREAM_GETC(s
, node
->node_flag
);
1183 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1184 STREAM_GETC(s
, node
->type
);
1185 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1186 STREAM_GETL(s
, node
->as_number
);
1187 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1188 STREAM_GETL(s
, node
->srgb
.lower_bound
);
1189 STREAM_GETL(s
, node
->srgb
.range_size
);
1190 STREAM_GETC(s
, node
->srgb
.flag
);
1191 STREAM_GET(node
->algo
, s
, 2);
1193 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1194 STREAM_GETL(s
, node
->srlb
.lower_bound
);
1195 STREAM_GETL(s
, node
->srlb
.range_size
);
1197 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1198 STREAM_GETC(s
, node
->msd
);
1203 zlog_err("LS(%s): Could not parse Link State Node. Abort!", __func__
);
1204 XFREE(MTYPE_LS_DB
, node
);
1208 static struct ls_attributes
*ls_parse_attributes(struct stream
*s
)
1210 struct ls_attributes
*attr
;
1213 attr
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
1216 STREAM_GET(&attr
->adv
, s
, sizeof(struct ls_node_id
));
1217 STREAM_GETL(s
, attr
->flags
);
1218 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1219 STREAM_GETC(s
, len
);
1220 STREAM_GET(attr
->name
, s
, len
);
1222 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1223 STREAM_GETL(s
, attr
->metric
);
1224 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1225 STREAM_GETL(s
, attr
->standard
.te_metric
);
1226 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1227 STREAM_GETL(s
, attr
->standard
.admin_group
);
1228 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1229 attr
->standard
.local
.s_addr
= stream_get_ipv4(s
);
1230 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1231 attr
->standard
.remote
.s_addr
= stream_get_ipv4(s
);
1232 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1233 STREAM_GET(&attr
->standard
.local6
, s
, IPV6_MAX_BYTELEN
);
1234 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1235 STREAM_GET(&attr
->standard
.remote6
, s
, IPV6_MAX_BYTELEN
);
1236 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1237 STREAM_GETL(s
, attr
->standard
.local_id
);
1238 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1239 STREAM_GETL(s
, attr
->standard
.remote_id
);
1240 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1241 STREAM_GETF(s
, attr
->standard
.max_bw
);
1242 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1243 STREAM_GETF(s
, attr
->standard
.max_rsv_bw
);
1244 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1245 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1246 STREAM_GETF(s
, attr
->standard
.unrsv_bw
[len
]);
1247 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1248 STREAM_GETL(s
, attr
->standard
.remote_as
);
1249 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1250 attr
->standard
.remote_addr
.s_addr
= stream_get_ipv4(s
);
1251 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1252 STREAM_GET(&attr
->standard
.remote_addr6
, s
, IPV6_MAX_BYTELEN
);
1253 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1254 STREAM_GETL(s
, attr
->extended
.delay
);
1255 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1256 STREAM_GETL(s
, attr
->extended
.min_delay
);
1257 STREAM_GETL(s
, attr
->extended
.max_delay
);
1259 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1260 STREAM_GETL(s
, attr
->extended
.jitter
);
1261 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1262 STREAM_GETL(s
, attr
->extended
.pkt_loss
);
1263 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1264 STREAM_GETF(s
, attr
->extended
.ava_bw
);
1265 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1266 STREAM_GETF(s
, attr
->extended
.rsv_bw
);
1267 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1268 STREAM_GETF(s
, attr
->extended
.used_bw
);
1269 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1270 STREAM_GETL(s
, attr
->adj_sid
[0].sid
);
1271 STREAM_GETC(s
, attr
->adj_sid
[0].flags
);
1272 STREAM_GETC(s
, attr
->adj_sid
[0].weight
);
1273 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1274 STREAM_GET(attr
->adj_sid
[0].neighbor
.sysid
, s
,
1276 else if (attr
->adv
.origin
== OSPFv2
)
1277 attr
->adj_sid
[0].neighbor
.addr
.s_addr
=
1280 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1281 STREAM_GETL(s
, attr
->adj_sid
[1].sid
);
1282 STREAM_GETC(s
, attr
->adj_sid
[1].flags
);
1283 STREAM_GETC(s
, attr
->adj_sid
[1].weight
);
1284 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1285 STREAM_GET(attr
->adj_sid
[1].neighbor
.sysid
, s
,
1287 else if (attr
->adv
.origin
== OSPFv2
)
1288 attr
->adj_sid
[1].neighbor
.addr
.s_addr
=
1291 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1292 STREAM_GETC(s
, len
);
1293 attr
->srlgs
= XCALLOC(MTYPE_LS_DB
, len
*sizeof(uint32_t));
1294 attr
->srlg_len
= len
;
1295 for (len
= 0; len
< attr
->srlg_len
; len
++)
1296 STREAM_GETL(s
, attr
->srlgs
[len
]);
1302 zlog_err("LS(%s): Could not parse Link State Attributes. Abort!",
1304 /* Clean memory allocation */
1305 if (attr
->srlgs
!= NULL
)
1306 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
1307 XFREE(MTYPE_LS_DB
, attr
);
1312 static struct ls_prefix
*ls_parse_prefix(struct stream
*s
)
1314 struct ls_prefix
*ls_pref
;
1317 ls_pref
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_prefix
));
1319 STREAM_GET(&ls_pref
->adv
, s
, sizeof(struct ls_node_id
));
1320 STREAM_GETW(s
, ls_pref
->flags
);
1321 STREAM_GETC(s
, ls_pref
->pref
.family
);
1322 STREAM_GETW(s
, ls_pref
->pref
.prefixlen
);
1323 len
= prefix_blen(&ls_pref
->pref
);
1324 STREAM_GET(&ls_pref
->pref
.u
.prefix
, s
, len
);
1325 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1326 STREAM_GETC(s
, ls_pref
->igp_flag
);
1327 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1328 STREAM_GETL(s
, ls_pref
->route_tag
);
1329 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1330 STREAM_GETQ(s
, ls_pref
->extended_tag
);
1331 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1332 STREAM_GETL(s
, ls_pref
->metric
);
1333 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1334 STREAM_GETL(s
, ls_pref
->sr
.sid
);
1335 STREAM_GETC(s
, ls_pref
->sr
.sid_flag
);
1336 STREAM_GETC(s
, ls_pref
->sr
.algo
);
1342 zlog_err("LS(%s): Could not parse Link State Prefix. Abort!", __func__
);
1343 XFREE(MTYPE_LS_DB
, ls_pref
);
1347 struct ls_message
*ls_parse_msg(struct stream
*s
)
1349 struct ls_message
*msg
;
1351 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1353 /* Read LS Message header */
1354 STREAM_GETC(s
, msg
->event
);
1355 STREAM_GETC(s
, msg
->type
);
1356 STREAM_GET(&msg
->remote_id
, s
, sizeof(struct ls_node_id
));
1358 /* Read Message Payload */
1359 switch (msg
->type
) {
1360 case LS_MSG_TYPE_NODE
:
1361 msg
->data
.node
= ls_parse_node(s
);
1363 case LS_MSG_TYPE_ATTRIBUTES
:
1364 msg
->data
.attr
= ls_parse_attributes(s
);
1366 case LS_MSG_TYPE_PREFIX
:
1367 msg
->data
.prefix
= ls_parse_prefix(s
);
1370 zlog_err("Unsupported Payload");
1371 goto stream_failure
;
1374 if (msg
->data
.node
== NULL
|| msg
->data
.attr
== NULL
1375 || msg
->data
.prefix
== NULL
)
1376 goto stream_failure
;
1381 zlog_err("LS(%s): Could not parse LS message. Abort!", __func__
);
1382 XFREE(MTYPE_LS_DB
, msg
);
1386 static int ls_format_node(struct stream
*s
, struct ls_node
*node
)
1390 /* Push Advertise node information first */
1391 stream_put(s
, &node
->adv
, sizeof(struct ls_node_id
));
1393 /* Push Flags & Origin then Node information if there are present */
1394 stream_putw(s
, node
->flags
);
1395 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1396 len
= strlen(node
->name
);
1397 stream_putc(s
, len
+ 1);
1398 stream_put(s
, node
->name
, len
);
1399 stream_putc(s
, '\0');
1401 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1402 stream_put_ipv4(s
, node
->router_id
.s_addr
);
1403 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1404 stream_put(s
, &node
->router6_id
, IPV6_MAX_BYTELEN
);
1405 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1406 stream_putc(s
, node
->node_flag
);
1407 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1408 stream_putc(s
, node
->type
);
1409 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1410 stream_putl(s
, node
->as_number
);
1411 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1412 stream_putl(s
, node
->srgb
.lower_bound
);
1413 stream_putl(s
, node
->srgb
.range_size
);
1414 stream_putc(s
, node
->srgb
.flag
);
1415 stream_put(s
, node
->algo
, 2);
1417 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1418 stream_putl(s
, node
->srlb
.lower_bound
);
1419 stream_putl(s
, node
->srlb
.range_size
);
1421 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1422 stream_putc(s
, node
->msd
);
1427 static int ls_format_attributes(struct stream
*s
, struct ls_attributes
*attr
)
1431 /* Push Advertise node information first */
1432 stream_put(s
, &attr
->adv
, sizeof(struct ls_node_id
));
1434 /* Push Flags & Origin then LS attributes if there are present */
1435 stream_putl(s
, attr
->flags
);
1436 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1437 len
= strlen(attr
->name
);
1438 stream_putc(s
, len
+ 1);
1439 stream_put(s
, attr
->name
, len
);
1440 stream_putc(s
, '\0');
1442 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1443 stream_putl(s
, attr
->metric
);
1444 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1445 stream_putl(s
, attr
->standard
.te_metric
);
1446 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1447 stream_putl(s
, attr
->standard
.admin_group
);
1448 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1449 stream_put_ipv4(s
, attr
->standard
.local
.s_addr
);
1450 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1451 stream_put_ipv4(s
, attr
->standard
.remote
.s_addr
);
1452 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1453 stream_put(s
, &attr
->standard
.local6
, IPV6_MAX_BYTELEN
);
1454 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1455 stream_put(s
, &attr
->standard
.remote6
, IPV6_MAX_BYTELEN
);
1456 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1457 stream_putl(s
, attr
->standard
.local_id
);
1458 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1459 stream_putl(s
, attr
->standard
.remote_id
);
1460 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1461 stream_putf(s
, attr
->standard
.max_bw
);
1462 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1463 stream_putf(s
, attr
->standard
.max_rsv_bw
);
1464 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1465 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1466 stream_putf(s
, attr
->standard
.unrsv_bw
[len
]);
1467 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1468 stream_putl(s
, attr
->standard
.remote_as
);
1469 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1470 stream_put_ipv4(s
, attr
->standard
.remote_addr
.s_addr
);
1471 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1472 stream_put(s
, &attr
->standard
.remote_addr6
, IPV6_MAX_BYTELEN
);
1473 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1474 stream_putl(s
, attr
->extended
.delay
);
1475 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1476 stream_putl(s
, attr
->extended
.min_delay
);
1477 stream_putl(s
, attr
->extended
.max_delay
);
1479 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1480 stream_putl(s
, attr
->extended
.jitter
);
1481 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1482 stream_putl(s
, attr
->extended
.pkt_loss
);
1483 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1484 stream_putf(s
, attr
->extended
.ava_bw
);
1485 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1486 stream_putf(s
, attr
->extended
.rsv_bw
);
1487 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1488 stream_putf(s
, attr
->extended
.used_bw
);
1489 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1490 stream_putl(s
, attr
->adj_sid
[0].sid
);
1491 stream_putc(s
, attr
->adj_sid
[0].flags
);
1492 stream_putc(s
, attr
->adj_sid
[0].weight
);
1493 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1494 stream_put(s
, attr
->adj_sid
[0].neighbor
.sysid
,
1496 else if (attr
->adv
.origin
== OSPFv2
)
1498 attr
->adj_sid
[0].neighbor
.addr
.s_addr
);
1500 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1501 stream_putl(s
, attr
->adj_sid
[1].sid
);
1502 stream_putc(s
, attr
->adj_sid
[1].flags
);
1503 stream_putc(s
, attr
->adj_sid
[1].weight
);
1504 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1505 stream_put(s
, attr
->adj_sid
[1].neighbor
.sysid
,
1507 else if (attr
->adv
.origin
== OSPFv2
)
1509 attr
->adj_sid
[1].neighbor
.addr
.s_addr
);
1511 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1512 stream_putc(s
, attr
->srlg_len
);
1513 for (len
= 0; len
< attr
->srlg_len
; len
++)
1514 stream_putl(s
, attr
->srlgs
[len
]);
1520 static int ls_format_prefix(struct stream
*s
, struct ls_prefix
*ls_pref
)
1524 /* Push Advertise node information first */
1525 stream_put(s
, &ls_pref
->adv
, sizeof(struct ls_node_id
));
1527 /* Push Flags, Origin & Prefix then information if there are present */
1528 stream_putw(s
, ls_pref
->flags
);
1529 stream_putc(s
, ls_pref
->pref
.family
);
1530 stream_putw(s
, ls_pref
->pref
.prefixlen
);
1531 len
= prefix_blen(&ls_pref
->pref
);
1532 stream_put(s
, &ls_pref
->pref
.u
.prefix
, len
);
1533 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1534 stream_putc(s
, ls_pref
->igp_flag
);
1535 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1536 stream_putl(s
, ls_pref
->route_tag
);
1537 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1538 stream_putq(s
, ls_pref
->extended_tag
);
1539 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1540 stream_putl(s
, ls_pref
->metric
);
1541 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1542 stream_putl(s
, ls_pref
->sr
.sid
);
1543 stream_putc(s
, ls_pref
->sr
.sid_flag
);
1544 stream_putc(s
, ls_pref
->sr
.algo
);
1550 static int ls_format_msg(struct stream
*s
, struct ls_message
*msg
)
1553 /* Prepare Link State header */
1554 stream_putc(s
, msg
->event
);
1555 stream_putc(s
, msg
->type
);
1556 stream_put(s
, &msg
->remote_id
, sizeof(struct ls_node_id
));
1558 /* Add Message Payload */
1559 switch (msg
->type
) {
1560 case LS_MSG_TYPE_NODE
:
1561 return ls_format_node(s
, msg
->data
.node
);
1562 case LS_MSG_TYPE_ATTRIBUTES
:
1563 return ls_format_attributes(s
, msg
->data
.attr
);
1564 case LS_MSG_TYPE_PREFIX
:
1565 return ls_format_prefix(s
, msg
->data
.prefix
);
1567 zlog_warn("Unsupported Payload");
1574 int ls_send_msg(struct zclient
*zclient
, struct ls_message
*msg
,
1575 struct zapi_opaque_reg_info
*dst
)
1580 /* Check if we have a valid message */
1581 if (msg
->event
== LS_MSG_EVENT_UNDEF
)
1584 /* Check buffer size */
1585 if (STREAM_SIZE(zclient
->obuf
) <
1586 (ZEBRA_HEADER_SIZE
+ sizeof(uint32_t) + sizeof(msg
)))
1592 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
1594 /* Set sub-type, flags and destination for unicast message */
1595 stream_putl(s
, LINK_STATE_UPDATE
);
1597 SET_FLAG(flags
, ZAPI_OPAQUE_FLAG_UNICAST
);
1598 stream_putw(s
, flags
);
1599 /* Send destination client info */
1600 stream_putc(s
, dst
->proto
);
1601 stream_putw(s
, dst
->instance
);
1602 stream_putl(s
, dst
->session_id
);
1604 stream_putw(s
, flags
);
1607 /* Format Link State message */
1608 if (ls_format_msg(s
, msg
) < 0) {
1613 /* Put length into the header at the start of the stream. */
1614 stream_putw_at(s
, 0, stream_get_endp(s
));
1616 return zclient_send_message(zclient
);
1619 struct ls_message
*ls_vertex2msg(struct ls_message
*msg
,
1620 struct ls_vertex
*vertex
)
1622 /* Allocate space if needed */
1624 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1626 memset(msg
, 0, sizeof(*msg
));
1628 msg
->type
= LS_MSG_TYPE_NODE
;
1629 switch (vertex
->status
) {
1631 msg
->event
= LS_MSG_EVENT_ADD
;
1634 msg
->event
= LS_MSG_EVENT_UPDATE
;
1637 msg
->event
= LS_MSG_EVENT_DELETE
;
1640 msg
->event
= LS_MSG_EVENT_SYNC
;
1643 msg
->event
= LS_MSG_EVENT_UNDEF
;
1646 msg
->data
.node
= vertex
->node
;
1647 msg
->remote_id
.origin
= UNKNOWN
;
1652 struct ls_message
*ls_edge2msg(struct ls_message
*msg
, struct ls_edge
*edge
)
1654 /* Allocate space if needed */
1656 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1658 memset(msg
, 0, sizeof(*msg
));
1660 msg
->type
= LS_MSG_TYPE_ATTRIBUTES
;
1661 switch (edge
->status
) {
1663 msg
->event
= LS_MSG_EVENT_ADD
;
1666 msg
->event
= LS_MSG_EVENT_UPDATE
;
1669 msg
->event
= LS_MSG_EVENT_DELETE
;
1672 msg
->event
= LS_MSG_EVENT_SYNC
;
1675 msg
->event
= LS_MSG_EVENT_UNDEF
;
1678 msg
->data
.attr
= edge
->attributes
;
1679 if (edge
->destination
!= NULL
)
1680 msg
->remote_id
= edge
->destination
->node
->adv
;
1682 msg
->remote_id
.origin
= UNKNOWN
;
1687 struct ls_message
*ls_subnet2msg(struct ls_message
*msg
,
1688 struct ls_subnet
*subnet
)
1690 /* Allocate space if needed */
1692 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1694 memset(msg
, 0, sizeof(*msg
));
1696 msg
->type
= LS_MSG_TYPE_PREFIX
;
1697 switch (subnet
->status
) {
1699 msg
->event
= LS_MSG_EVENT_ADD
;
1702 msg
->event
= LS_MSG_EVENT_UPDATE
;
1705 msg
->event
= LS_MSG_EVENT_DELETE
;
1708 msg
->event
= LS_MSG_EVENT_SYNC
;
1711 msg
->event
= LS_MSG_EVENT_UNDEF
;
1714 msg
->data
.prefix
= subnet
->ls_pref
;
1715 msg
->remote_id
.origin
= UNKNOWN
;
1720 struct ls_vertex
*ls_msg2vertex(struct ls_ted
*ted
, struct ls_message
*msg
,
1723 struct ls_node
*node
= (struct ls_node
*)msg
->data
.node
;
1724 struct ls_vertex
*vertex
= NULL
;
1726 switch (msg
->event
) {
1727 case LS_MSG_EVENT_SYNC
:
1728 vertex
= ls_vertex_add(ted
, node
);
1730 vertex
->status
= SYNC
;
1732 case LS_MSG_EVENT_ADD
:
1733 vertex
= ls_vertex_add(ted
, node
);
1735 vertex
->status
= NEW
;
1737 case LS_MSG_EVENT_UPDATE
:
1738 vertex
= ls_vertex_update(ted
, node
);
1740 vertex
->status
= UPDATE
;
1742 case LS_MSG_EVENT_DELETE
:
1743 vertex
= ls_find_vertex_by_id(ted
, node
->adv
);
1746 ls_vertex_del_all(ted
, vertex
);
1748 vertex
->status
= DELETE
;
1759 struct ls_edge
*ls_msg2edge(struct ls_ted
*ted
, struct ls_message
*msg
,
1762 struct ls_attributes
*attr
= (struct ls_attributes
*)msg
->data
.attr
;
1763 struct ls_edge
*edge
= NULL
;
1765 switch (msg
->event
) {
1766 case LS_MSG_EVENT_SYNC
:
1767 edge
= ls_edge_add(ted
, attr
);
1769 edge
->status
= SYNC
;
1771 case LS_MSG_EVENT_ADD
:
1772 edge
= ls_edge_add(ted
, attr
);
1776 case LS_MSG_EVENT_UPDATE
:
1777 edge
= ls_edge_update(ted
, attr
);
1779 edge
->status
= UPDATE
;
1781 case LS_MSG_EVENT_DELETE
:
1782 edge
= ls_find_edge_by_source(ted
, attr
);
1785 ls_edge_del_all(ted
, edge
);
1787 edge
->status
= DELETE
;
1798 struct ls_subnet
*ls_msg2subnet(struct ls_ted
*ted
, struct ls_message
*msg
,
1801 struct ls_prefix
*pref
= (struct ls_prefix
*)msg
->data
.prefix
;
1802 struct ls_subnet
*subnet
= NULL
;
1804 switch (msg
->event
) {
1805 case LS_MSG_EVENT_SYNC
:
1806 subnet
= ls_subnet_add(ted
, pref
);
1808 subnet
->status
= SYNC
;
1810 case LS_MSG_EVENT_ADD
:
1811 subnet
= ls_subnet_add(ted
, pref
);
1813 subnet
->status
= NEW
;
1815 case LS_MSG_EVENT_UPDATE
:
1816 subnet
= ls_subnet_update(ted
, pref
);
1818 subnet
->status
= UPDATE
;
1820 case LS_MSG_EVENT_DELETE
:
1821 subnet
= ls_find_subnet(ted
, pref
->pref
);
1824 ls_subnet_del_all(ted
, subnet
);
1826 subnet
->status
= DELETE
;
1837 struct ls_element
*ls_msg2ted(struct ls_ted
*ted
, struct ls_message
*msg
,
1840 struct ls_element
*lse
= NULL
;
1842 switch (msg
->type
) {
1843 case LS_MSG_TYPE_NODE
:
1844 lse
= (struct ls_element
*)ls_msg2vertex(ted
, msg
, delete);
1846 case LS_MSG_TYPE_ATTRIBUTES
:
1847 lse
= (struct ls_element
*)ls_msg2edge(ted
, msg
, delete);
1849 case LS_MSG_TYPE_PREFIX
:
1850 lse
= (struct ls_element
*)ls_msg2subnet(ted
, msg
, delete);
1860 struct ls_element
*ls_stream2ted(struct ls_ted
*ted
, struct stream
*s
,
1863 struct ls_message
*msg
;
1864 struct ls_element
*lse
= NULL
;
1866 msg
= ls_parse_msg(s
);
1868 lse
= ls_msg2ted(ted
, msg
, delete);
1875 void ls_delete_msg(struct ls_message
*msg
)
1880 XFREE(MTYPE_LS_DB
, msg
);
1883 int ls_sync_ted(struct ls_ted
*ted
, struct zclient
*zclient
,
1884 struct zapi_opaque_reg_info
*dst
)
1886 struct ls_vertex
*vertex
;
1887 struct ls_edge
*edge
;
1888 struct ls_subnet
*subnet
;
1889 struct ls_message msg
;
1891 /* Loop TED, start sending Node, then Attributes and finally Prefix */
1892 frr_each(vertices
, &ted
->vertices
, vertex
) {
1893 ls_vertex2msg(&msg
, vertex
);
1894 ls_send_msg(zclient
, &msg
, dst
);
1896 frr_each(edges
, &ted
->edges
, edge
) {
1897 ls_edge2msg(&msg
, edge
);
1898 ls_send_msg(zclient
, &msg
, dst
);
1900 frr_each(subnets
, &ted
->subnets
, subnet
) {
1901 ls_subnet2msg(&msg
, subnet
);
1902 ls_send_msg(zclient
, &msg
, dst
);
1908 * Link State Show functions
1910 static const char *const origin2txt
[] = {
1919 static const char *const type2txt
[] = {
1928 static const char *const status2txt
[] = {
1937 static const char *ls_node_id_to_text(struct ls_node_id lnid
, char *str
,
1940 if (lnid
.origin
== ISIS_L1
|| lnid
.origin
== ISIS_L2
) {
1943 id
= lnid
.id
.iso
.sys_id
;
1944 snprintfrr(str
, size
, "%02x%02x.%02x%02x.%02x%02x", id
[0],
1945 id
[1], id
[2], id
[3], id
[4], id
[5]);
1947 snprintfrr(str
, size
, "%pI4", &lnid
.id
.ip
.addr
);
1952 static void ls_show_vertex_vty(struct ls_vertex
*vertex
, struct vty
*vty
,
1955 struct listnode
*node
;
1956 struct ls_node
*lsn
;
1957 struct ls_edge
*edge
;
1958 struct ls_subnet
*subnet
;
1968 sbuf_init(&sbuf
, NULL
, 0);
1970 sbuf_push(&sbuf
, 2, "Vertex (%" PRIu64
"): %s", vertex
->key
, lsn
->name
);
1971 sbuf_push(&sbuf
, 0, "\tRouter Id: %pI4", &lsn
->router_id
);
1972 sbuf_push(&sbuf
, 0, "\tOrigin: %s", origin2txt
[lsn
->adv
.origin
]);
1973 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[vertex
->status
]);
1977 "\t%d Outgoing Edges, %d Incoming Edges, %d Subnets\n",
1978 listcount(vertex
->outgoing_edges
),
1979 listcount(vertex
->incoming_edges
),
1980 listcount(vertex
->prefixes
));
1984 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
1985 sbuf_push(&sbuf
, 4, "Type: %s\n", type2txt
[lsn
->type
]);
1986 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
1987 sbuf_push(&sbuf
, 4, "AS number: %u\n", lsn
->as_number
);
1988 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
1989 sbuf_push(&sbuf
, 4, "Segment Routing Capabilities:\n");
1990 upper
= lsn
->srgb
.lower_bound
+ lsn
->srgb
.range_size
- 1;
1991 sbuf_push(&sbuf
, 8, "SRGB: [%d/%d]", lsn
->srgb
.lower_bound
,
1993 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
1994 upper
= lsn
->srlb
.lower_bound
+ lsn
->srlb
.range_size
1996 sbuf_push(&sbuf
, 0, "\tSRLB: [%d/%d]",
1997 lsn
->srlb
.lower_bound
, upper
);
1999 sbuf_push(&sbuf
, 0, "\tAlgo: ");
2000 for (int i
= 0; i
< 2; i
++) {
2001 if (lsn
->algo
[i
] == 255)
2005 lsn
->algo
[i
] == 0 ? "SPF " : "S-SPF ");
2007 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
2008 sbuf_push(&sbuf
, 0, "\tMSD: %d", lsn
->msd
);
2009 sbuf_push(&sbuf
, 0, "\n");
2012 sbuf_push(&sbuf
, 4, "Outgoing Edges: %d\n",
2013 listcount(vertex
->outgoing_edges
));
2014 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, node
, edge
)) {
2015 if (edge
->destination
) {
2016 lsn
= edge
->destination
->node
;
2017 sbuf_push(&sbuf
, 6, "To:\t%s(%pI4)", lsn
->name
,
2020 sbuf_push(&sbuf
, 6, "To:\t- (0.0.0.0)");
2022 sbuf_push(&sbuf
, 0, "\tLocal: %pI4\tRemote: %pI4\n",
2023 &edge
->attributes
->standard
.local
,
2024 &edge
->attributes
->standard
.remote
);
2027 sbuf_push(&sbuf
, 4, "Incoming Edges: %d\n",
2028 listcount(vertex
->incoming_edges
));
2029 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, node
, edge
)) {
2031 lsn
= edge
->source
->node
;
2032 sbuf_push(&sbuf
, 6, "From:\t%s(%pI4)", lsn
->name
,
2035 sbuf_push(&sbuf
, 6, "From:\t- (0.0.0.0)");
2037 sbuf_push(&sbuf
, 0, "\tRemote: %pI4\tLocal: %pI4\n",
2038 &edge
->attributes
->standard
.local
,
2039 &edge
->attributes
->standard
.remote
);
2042 sbuf_push(&sbuf
, 4, "Subnets: %d\n", listcount(vertex
->prefixes
));
2043 for (ALL_LIST_ELEMENTS_RO(vertex
->prefixes
, node
, subnet
))
2044 sbuf_push(&sbuf
, 6, "Prefix:\t%pFX\n", &subnet
->key
);
2047 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2051 static void ls_show_vertex_json(struct ls_vertex
*vertex
,
2052 struct json_object
*json
)
2054 struct ls_node
*lsn
;
2055 json_object
*jsr
, *jalgo
, *jobj
;
2056 char buf
[INET6_BUFSIZ
];
2064 json_object_int_add(json
, "vertex-id", vertex
->key
);
2065 json_object_string_add(json
, "status", status2txt
[vertex
->status
]);
2066 json_object_string_add(json
, "origin", origin2txt
[lsn
->adv
.origin
]);
2067 if (CHECK_FLAG(lsn
->flags
, LS_NODE_NAME
))
2068 json_object_string_add(json
, "name", lsn
->name
);
2069 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID
)) {
2070 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &lsn
->router_id
);
2071 json_object_string_add(json
, "router-id", buf
);
2073 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID6
)) {
2074 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &lsn
->router6_id
);
2075 json_object_string_add(json
, "router-id-v6", buf
);
2077 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
2078 json_object_string_add(json
, "vertex-type",
2079 type2txt
[lsn
->type
]);
2080 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
2081 json_object_int_add(json
, "asn", lsn
->as_number
);
2082 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
2083 jsr
= json_object_new_object();
2084 json_object_object_add(json
, "segment-routing", jsr
);
2085 json_object_int_add(jsr
, "srgb-size", lsn
->srgb
.range_size
);
2086 json_object_int_add(jsr
, "srgb-lower", lsn
->srgb
.lower_bound
);
2087 jalgo
= json_object_new_array();
2088 json_object_object_add(jsr
, "algorithms", jalgo
);
2089 for (int i
= 0; i
< 2; i
++) {
2090 if (lsn
->algo
[i
] == 255)
2092 jobj
= json_object_new_object();
2094 snprintfrr(buf
, 2, "%u", i
);
2095 json_object_string_add(
2096 jobj
, buf
, lsn
->algo
[i
] == 0 ? "SPF" : "S-SPF");
2097 json_object_array_add(jalgo
, jobj
);
2099 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
2100 json_object_int_add(jsr
, "srlb-size",
2101 lsn
->srlb
.range_size
);
2102 json_object_int_add(jsr
, "srlb-lower",
2103 lsn
->srlb
.lower_bound
);
2105 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
2106 json_object_int_add(jsr
, "msd", lsn
->msd
);
2110 void ls_show_vertex(struct ls_vertex
*vertex
, struct vty
*vty
,
2111 struct json_object
*json
, bool verbose
)
2114 ls_show_vertex_json(vertex
, json
);
2116 ls_show_vertex_vty(vertex
, vty
, verbose
);
2119 void ls_show_vertices(struct ls_ted
*ted
, struct vty
*vty
,
2120 struct json_object
*json
, bool verbose
)
2122 struct ls_vertex
*vertex
;
2123 json_object
*jnodes
, *jnode
;
2126 jnodes
= json_object_new_array();
2127 json_object_object_add(json
, "vertices", jnodes
);
2128 frr_each (vertices
, &ted
->vertices
, vertex
) {
2129 jnode
= json_object_new_object();
2130 ls_show_vertex(vertex
, NULL
, jnode
, verbose
);
2131 json_object_array_add(jnodes
, jnode
);
2134 frr_each (vertices
, &ted
->vertices
, vertex
)
2135 ls_show_vertex(vertex
, vty
, NULL
, verbose
);
2139 static void ls_show_edge_vty(struct ls_edge
*edge
, struct vty
*vty
,
2142 struct ls_attributes
*attr
;
2144 char buf
[INET6_BUFSIZ
];
2146 attr
= edge
->attributes
;
2147 sbuf_init(&sbuf
, NULL
, 0);
2149 sbuf_push(&sbuf
, 2, "Edge (%" PRIu64
"): ", edge
->key
);
2150 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
2151 sbuf_push(&sbuf
, 0, "%pI4", &attr
->standard
.local
);
2152 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
2153 sbuf_push(&sbuf
, 0, "%pI6", &attr
->standard
.local6
);
2155 sbuf_push(&sbuf
, 0, "%u/%u", attr
->standard
.local_id
,
2156 attr
->standard
.remote_id
);
2157 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
2158 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
2159 sbuf_push(&sbuf
, 0, "\tMetric: %u", attr
->metric
);
2160 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[edge
->status
]);
2165 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[attr
->adv
.origin
]);
2166 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2167 sbuf_push(&sbuf
, 4, "Name: %s\n", attr
->name
);
2168 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2169 sbuf_push(&sbuf
, 4, "TE Metric: %u\n",
2170 attr
->standard
.te_metric
);
2171 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2172 sbuf_push(&sbuf
, 4, "Admin Group: 0x%x\n",
2173 attr
->standard
.admin_group
);
2174 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
2175 sbuf_push(&sbuf
, 4, "Local IPv4 address: %pI4\n",
2176 &attr
->standard
.local
);
2177 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
2178 sbuf_push(&sbuf
, 4, "Remote IPv4 address: %pI4\n",
2179 &attr
->standard
.remote
);
2180 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
2181 sbuf_push(&sbuf
, 4, "Local IPv6 address: %pI6\n",
2182 &attr
->standard
.local6
);
2183 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
2184 sbuf_push(&sbuf
, 4, "Remote IPv6 address: %pI6\n",
2185 &attr
->standard
.remote6
);
2186 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2187 sbuf_push(&sbuf
, 4, "Local Identifier: %u\n",
2188 attr
->standard
.local_id
);
2189 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2190 sbuf_push(&sbuf
, 4, "Remote Identifier: %u\n",
2191 attr
->standard
.remote_id
);
2192 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2193 sbuf_push(&sbuf
, 4, "Maximum Bandwidth: %g (Bytes/s)\n",
2194 attr
->standard
.max_bw
);
2195 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2197 "Maximum Reservable Bandwidth: %g (Bytes/s)\n",
2198 attr
->standard
.max_rsv_bw
);
2199 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2200 sbuf_push(&sbuf
, 4, "Unreserved Bandwidth per Class Type\n");
2201 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
+= 2)
2203 "[%d]: %g (Bytes/sec)\t[%d]: %g (Bytes/s)\n",
2204 i
, attr
->standard
.unrsv_bw
[i
], i
+ 1,
2205 attr
->standard
.unrsv_bw
[i
+ 1]);
2207 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2208 sbuf_push(&sbuf
, 4, "Remote AS: %u\n",
2209 attr
->standard
.remote_as
);
2210 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
2211 sbuf_push(&sbuf
, 4, "Remote ASBR IPv4 address: %pI4\n",
2212 &attr
->standard
.remote_addr
);
2213 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
2214 sbuf_push(&sbuf
, 4, "Remote ASBR IPv6 address: %pI6\n",
2215 &attr
->standard
.remote_addr6
);
2216 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2217 sbuf_push(&sbuf
, 4, "Average Link Delay: %d (micro-sec)\n",
2218 attr
->extended
.delay
);
2219 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
))
2220 sbuf_push(&sbuf
, 4, "Min/Max Link Delay: %d/%d (micro-sec)\n",
2221 attr
->extended
.min_delay
, attr
->extended
.max_delay
);
2222 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2223 sbuf_push(&sbuf
, 4, "Delay Variation: %d (micro-sec)\n",
2224 attr
->extended
.jitter
);
2225 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2226 sbuf_push(&sbuf
, 4, "Link Loss: %g (%%)\n",
2227 (float)(attr
->extended
.pkt_loss
* LOSS_PRECISION
));
2228 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2229 sbuf_push(&sbuf
, 4, "Available Bandwidth: %g (Bytes/s)\n",
2230 attr
->extended
.ava_bw
);
2231 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2232 sbuf_push(&sbuf
, 4, "Residual Bandwidth: %g (Bytes/s)\n",
2233 attr
->extended
.rsv_bw
);
2234 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2235 sbuf_push(&sbuf
, 4, "Utilized Bandwidth: %g (Bytes/s)\n",
2236 attr
->extended
.used_bw
);
2237 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2238 sbuf_push(&sbuf
, 4, "Adjacency-SID: %u", attr
->adj_sid
[0].sid
);
2239 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2240 attr
->adj_sid
[0].flags
, attr
->adj_sid
[0].weight
);
2242 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2243 sbuf_push(&sbuf
, 4, "Bck. Adjacency-SID: %u",
2244 attr
->adj_sid
[1].sid
);
2245 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2246 attr
->adj_sid
[1].flags
, attr
->adj_sid
[1].weight
);
2248 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2249 sbuf_push(&sbuf
, 4, "SRLGs: %d", attr
->srlg_len
);
2250 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2252 sbuf_push(&sbuf
, 8, "\n%u", attr
->srlgs
[i
]);
2254 sbuf_push(&sbuf
, 8, ", %u", attr
->srlgs
[i
]);
2256 sbuf_push(&sbuf
, 0, "\n");
2260 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2264 static void ls_show_edge_json(struct ls_edge
*edge
, struct json_object
*json
)
2266 struct ls_attributes
*attr
;
2267 struct json_object
*jte
, *jbw
, *jobj
, *jsr
= NULL
, *jsrlg
;
2268 char buf
[INET6_BUFSIZ
];
2270 attr
= edge
->attributes
;
2272 json_object_int_add(json
, "edge-id", edge
->key
);
2273 json_object_string_add(json
, "status", status2txt
[edge
->status
]);
2274 json_object_string_add(json
, "origin", origin2txt
[attr
->adv
.origin
]);
2275 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
2276 json_object_string_add(json
, "advertised-router", buf
);
2278 json_object_int_add(json
, "local-vertex-id", edge
->source
->key
);
2279 if (edge
->destination
)
2280 json_object_int_add(json
, "remote-vertex-id",
2281 edge
->destination
->key
);
2282 json_object_int_add(json
, "metric", attr
->metric
);
2283 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2284 json_object_string_add(json
, "name", attr
->name
);
2285 jte
= json_object_new_object();
2286 json_object_object_add(json
, "edge-attributes", jte
);
2287 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2288 json_object_int_add(jte
, "te-metric", attr
->standard
.te_metric
);
2289 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2290 json_object_int_add(jte
, "admin-group",
2291 attr
->standard
.admin_group
);
2292 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)) {
2293 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.local
);
2294 json_object_string_add(jte
, "local-address", buf
);
2296 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
)) {
2297 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.remote
);
2298 json_object_string_add(jte
, "remote-address", buf
);
2300 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)) {
2301 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.local6
);
2302 json_object_string_add(jte
, "local-address-v6", buf
);
2304 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
)) {
2305 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.remote6
);
2306 json_object_string_add(jte
, "remote-address-v6", buf
);
2308 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2309 json_object_int_add(jte
, "local-identifier",
2310 attr
->standard
.local_id
);
2311 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2312 json_object_int_add(jte
, "remote-identifier",
2313 attr
->standard
.remote_id
);
2314 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2315 json_object_double_add(jte
, "max-link-bandwidth",
2316 attr
->standard
.max_bw
);
2317 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2318 json_object_double_add(jte
, "max-resv-link-bandwidth",
2319 attr
->standard
.max_rsv_bw
);
2320 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2321 jbw
= json_object_new_array();
2322 json_object_object_add(jte
, "unreserved-bandwidth", jbw
);
2323 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
++) {
2324 jobj
= json_object_new_object();
2325 snprintfrr(buf
, 13, "class-type-%u", i
);
2326 json_object_double_add(jobj
, buf
,
2327 attr
->standard
.unrsv_bw
[i
]);
2328 json_object_array_add(jbw
, jobj
);
2331 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2332 json_object_int_add(jte
, "remote-asn",
2333 attr
->standard
.remote_as
);
2334 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
)) {
2335 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4",
2336 &attr
->standard
.remote_addr
);
2337 json_object_string_add(jte
, "remote-as-address", buf
);
2339 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
)) {
2340 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6",
2341 &attr
->standard
.remote_addr6
);
2342 json_object_string_add(jte
, "remote-as-address-v6", buf
);
2344 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2345 json_object_int_add(jte
, "delay", attr
->extended
.delay
);
2346 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
2347 json_object_int_add(jte
, "min-delay", attr
->extended
.min_delay
);
2348 json_object_int_add(jte
, "max-delay", attr
->extended
.max_delay
);
2350 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2351 json_object_int_add(jte
, "jitter", attr
->extended
.jitter
);
2352 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2353 json_object_double_add(
2354 jte
, "loss", attr
->extended
.pkt_loss
* LOSS_PRECISION
);
2355 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2356 json_object_double_add(jte
, "available-bandwidth",
2357 attr
->extended
.ava_bw
);
2358 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2359 json_object_double_add(jte
, "residual-bandwidth",
2360 attr
->extended
.rsv_bw
);
2361 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2362 json_object_double_add(jte
, "utilized-bandwidth",
2363 attr
->extended
.used_bw
);
2364 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2365 jsrlg
= json_object_new_array();
2366 json_object_object_add(jte
, "srlgs", jsrlg
);
2367 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2368 jobj
= json_object_new_object();
2369 json_object_int_add(jobj
, "srlg", attr
->srlgs
[i
]);
2370 json_object_array_add(jsrlg
, jobj
);
2373 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2374 jsr
= json_object_new_array();
2375 json_object_object_add(json
, "segment-routing", jsr
);
2376 jobj
= json_object_new_object();
2377 json_object_int_add(jobj
, "adj-sid", attr
->adj_sid
[0].sid
);
2378 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[0].flags
);
2379 json_object_string_add(jobj
, "flags", buf
);
2380 json_object_int_add(jobj
, "weight", attr
->adj_sid
[0].weight
);
2381 json_object_array_add(jsr
, jobj
);
2383 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2385 jsr
= json_object_new_array();
2386 json_object_object_add(json
, "segment-routing", jsr
);
2388 jobj
= json_object_new_object();
2389 json_object_int_add(jobj
, "adj-sid", attr
->adj_sid
[1].sid
);
2390 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[1].flags
);
2391 json_object_string_add(jobj
, "flags", buf
);
2392 json_object_int_add(jobj
, "weight", attr
->adj_sid
[1].weight
);
2393 json_object_array_add(jsr
, jobj
);
2397 void ls_show_edge(struct ls_edge
*edge
, struct vty
*vty
,
2398 struct json_object
*json
, bool verbose
)
2405 ls_show_edge_json(edge
, json
);
2407 ls_show_edge_vty(edge
, vty
, verbose
);
2410 void ls_show_edges(struct ls_ted
*ted
, struct vty
*vty
,
2411 struct json_object
*json
, bool verbose
)
2413 struct ls_edge
*edge
;
2414 json_object
*jedges
, *jedge
;
2417 jedges
= json_object_new_array();
2418 json_object_object_add(json
, "edges", jedges
);
2419 frr_each (edges
, &ted
->edges
, edge
) {
2420 jedge
= json_object_new_object();
2421 ls_show_edge(edge
, NULL
, jedge
, verbose
);
2422 json_object_array_add(jedges
, jedge
);
2425 frr_each (edges
, &ted
->edges
, edge
)
2426 ls_show_edge(edge
, vty
, NULL
, verbose
);
2430 static void ls_show_subnet_vty(struct ls_subnet
*subnet
, struct vty
*vty
,
2433 struct ls_prefix
*pref
;
2435 char buf
[INET6_BUFSIZ
];
2437 pref
= subnet
->ls_pref
;
2438 sbuf_init(&sbuf
, NULL
, 0);
2440 sbuf_push(&sbuf
, 2, "Subnet: %pFX", &subnet
->key
);
2441 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2442 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
2443 sbuf_push(&sbuf
, 0, "\tMetric: %d", pref
->metric
);
2444 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[subnet
->status
]);
2449 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[pref
->adv
.origin
]);
2450 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
))
2451 sbuf_push(&sbuf
, 4, "Flags: %d\n", pref
->igp_flag
);
2453 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2454 sbuf_push(&sbuf
, 4, "Tag: %d\n", pref
->route_tag
);
2456 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2457 sbuf_push(&sbuf
, 4, "Extended Tag: %" PRIu64
"\n",
2458 pref
->extended_tag
);
2460 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
))
2461 sbuf_push(&sbuf
, 4, "SID: %d\tAlgorithm: %d\tFlags: 0x%x\n",
2462 pref
->sr
.sid
, pref
->sr
.algo
, pref
->sr
.sid_flag
);
2465 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2469 static void ls_show_subnet_json(struct ls_subnet
*subnet
,
2470 struct json_object
*json
)
2472 struct ls_prefix
*pref
;
2474 char buf
[INET6_BUFSIZ
];
2476 pref
= subnet
->ls_pref
;
2478 snprintfrr(buf
, INET6_BUFSIZ
, "%pFX", &subnet
->key
);
2479 json_object_string_add(json
, "subnet-id", buf
);
2480 json_object_string_add(json
, "status", status2txt
[subnet
->status
]);
2481 json_object_string_add(json
, "origin", origin2txt
[pref
->adv
.origin
]);
2482 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2483 json_object_string_add(json
, "advertised-router", buf
);
2485 json_object_int_add(json
, "vertex-id", subnet
->vertex
->key
);
2486 json_object_int_add(json
, "metric", pref
->metric
);
2487 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
)) {
2488 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->igp_flag
);
2489 json_object_string_add(json
, "flags", buf
);
2491 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2492 json_object_int_add(json
, "tag", pref
->route_tag
);
2493 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2494 json_object_int_add(json
, "extended-tag", pref
->extended_tag
);
2495 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
)) {
2496 jsr
= json_object_new_object();
2497 json_object_object_add(json
, "segment-routing", jsr
);
2498 json_object_int_add(jsr
, "pref-sid", pref
->sr
.sid
);
2499 json_object_int_add(jsr
, "algo", pref
->sr
.algo
);
2500 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->sr
.sid_flag
);
2501 json_object_string_add(jsr
, "flags", buf
);
2505 void ls_show_subnet(struct ls_subnet
*subnet
, struct vty
*vty
,
2506 struct json_object
*json
, bool verbose
)
2513 ls_show_subnet_json(subnet
, json
);
2515 ls_show_subnet_vty(subnet
, vty
, verbose
);
2518 void ls_show_subnets(struct ls_ted
*ted
, struct vty
*vty
,
2519 struct json_object
*json
, bool verbose
)
2521 struct ls_subnet
*subnet
;
2522 json_object
*jsubs
, *jsub
;
2525 jsubs
= json_object_new_array();
2526 json_object_object_add(json
, "subnets", jsubs
);
2527 frr_each (subnets
, &ted
->subnets
, subnet
) {
2528 jsub
= json_object_new_object();
2529 ls_show_subnet(subnet
, NULL
, jsub
, verbose
);
2530 json_object_array_add(jsubs
, jsub
);
2533 frr_each (subnets
, &ted
->subnets
, subnet
)
2534 ls_show_subnet(subnet
, vty
, NULL
, verbose
);
2538 void ls_show_ted(struct ls_ted
*ted
, struct vty
*vty
, struct json_object
*json
,
2544 jted
= json_object_new_object();
2545 json_object_object_add(json
, "ted", jted
);
2546 json_object_string_add(jted
, "name", ted
->name
);
2547 json_object_int_add(jted
, "key", ted
->key
);
2548 json_object_int_add(jted
, "verticesCount",
2549 vertices_count(&ted
->vertices
));
2550 json_object_int_add(jted
, "edgesCount",
2551 edges_count(&ted
->edges
));
2552 json_object_int_add(jted
, "subnetsCount",
2553 subnets_count(&ted
->subnets
));
2554 ls_show_vertices(ted
, NULL
, jted
, verbose
);
2555 ls_show_edges(ted
, NULL
, jted
, verbose
);
2556 ls_show_subnets(ted
, NULL
, jted
, verbose
);
2562 "\n\tTraffic Engineering Database: %s (key: %d)\n\n",
2563 ted
->name
, ted
->key
);
2564 ls_show_vertices(ted
, vty
, NULL
, verbose
);
2565 ls_show_edges(ted
, vty
, NULL
, verbose
);
2566 ls_show_subnets(ted
, vty
, NULL
, verbose
);
2568 "\n\tTotal: %zu Vertices, %zu Edges, %zu Subnets\n\n",
2569 vertices_count(&ted
->vertices
),
2570 edges_count(&ted
->edges
), subnets_count(&ted
->subnets
));
2574 void ls_dump_ted(struct ls_ted
*ted
)
2576 struct ls_vertex
*vertex
;
2577 struct ls_edge
*edge
;
2578 struct ls_subnet
*subnet
;
2579 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
2581 zlog_debug("(%s) Ted init", __func__
);
2583 /* Loop TED, start printing Node, then Attributes and finally Prefix */
2584 frr_each (vertices
, &ted
->vertices
, vertex
) {
2585 zlog_debug(" Ted node (%s %pI4 %s)",
2586 vertex
->node
->name
[0] ? vertex
->node
->name
2588 &vertex
->node
->router_id
,
2589 origin2txt
[vertex
->node
->adv
.origin
]);
2590 struct listnode
*lst_node
;
2591 struct ls_edge
*vertex_edge
;
2593 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, lst_node
,
2596 " inc edge key:%" PRIu64
" attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2598 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2599 &vertex_edge
->attributes
->standard
.local
,
2600 &vertex_edge
->attributes
->standard
.remote
);
2602 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, lst_node
,
2605 " out edge key:%" PRIu64
" attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2607 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2608 &vertex_edge
->attributes
->standard
.local
,
2609 &vertex_edge
->attributes
->standard
.remote
);
2612 frr_each (edges
, &ted
->edges
, edge
) {
2613 zlog_debug(" Ted edge key:%" PRIu64
"src:%pI4 dst:%pI4", edge
->key
,
2614 edge
->source
? &edge
->source
->node
->router_id
2617 ? &edge
->destination
->node
->router_id
2620 frr_each (subnets
, &ted
->subnets
, subnet
) {
2621 zlog_debug(" Ted subnet key:%pFX vertex:%pI4",
2622 &subnet
->ls_pref
->pref
,
2623 &subnet
->vertex
->node
->adv
.id
.ip
.addr
);
2625 zlog_debug("(%s) Ted end", __func__
);