]>
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 struct ls_node
*ls_node_new(struct ls_node_id adv
, struct in_addr rid
,
54 if (adv
.origin
== UNKNOWN
)
57 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
59 if (!IPV4_NET0(rid
.s_addr
)) {
61 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID
);
63 if (adv
.origin
== OSPFv2
|| adv
.origin
== STATIC
64 || adv
.origin
== DIRECT
) {
65 new->router_id
= adv
.id
.ip
.addr
;
66 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID
);
69 if (!IN6_IS_ADDR_UNSPECIFIED(&rid6
)) {
70 new->router6_id
= rid6
;
71 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID6
);
76 void ls_node_del(struct ls_node
*node
)
81 XFREE(MTYPE_LS_DB
, node
);
85 int ls_node_same(struct ls_node
*n1
, struct ls_node
*n2
)
87 if ((n1
&& !n2
) || (!n1
&& n2
))
93 if (n1
->flags
!= n2
->flags
)
96 if (n1
->adv
.origin
!= n2
->adv
.origin
)
99 if (!memcmp(&n1
->adv
.id
, &n2
->adv
.id
, sizeof(struct ls_node_id
)))
102 /* Do we need to test individually each field, instead performing a
103 * global memcmp? There is a risk that an old value that is bit masked
104 * i.e. corresponding flag = 0, will result into a false negative
106 if (!memcmp(n1
, n2
, sizeof(struct ls_node
)))
113 * Link State Attributes management functions
115 struct ls_attributes
*ls_attributes_new(struct ls_node_id adv
,
116 struct in_addr local
,
117 struct in6_addr local6
,
120 struct ls_attributes
*new;
122 if (adv
.origin
== UNKNOWN
)
125 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
127 if (!IPV4_NET0(local
.s_addr
)) {
128 new->standard
.local
= local
;
129 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
);
131 if (!IN6_IS_ADDR_UNSPECIFIED(&local6
)) {
132 new->standard
.local6
= local6
;
133 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR6
);
136 new->standard
.local_id
= local_id
;
137 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ID
);
140 /* Check that almost one identifier is set */
141 if (!CHECK_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
| LS_ATTR_LOCAL_ADDR6
142 | LS_ATTR_LOCAL_ID
)) {
143 XFREE(MTYPE_LS_DB
, new);
150 void ls_attributes_srlg_del(struct ls_attributes
*attr
)
156 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
160 UNSET_FLAG(attr
->flags
, LS_ATTR_SRLG
);
163 void ls_attributes_del(struct ls_attributes
*attr
)
168 ls_attributes_srlg_del(attr
);
170 XFREE(MTYPE_LS_DB
, attr
);
174 int ls_attributes_same(struct ls_attributes
*l1
, struct ls_attributes
*l2
)
176 if ((l1
&& !l2
) || (!l1
&& l2
))
182 if (l1
->flags
!= l2
->flags
)
185 if (l1
->adv
.origin
!= l2
->adv
.origin
)
188 if (!memcmp(&l1
->adv
.id
, &l2
->adv
.id
, sizeof(struct ls_node_id
)))
191 /* Do we need to test individually each field, instead performing a
192 * global memcmp? There is a risk that an old value that is bit masked
193 * i.e. corresponding flag = 0, will result into a false negative
195 if (!memcmp(l1
, l2
, sizeof(struct ls_attributes
)))
202 * Link State prefix management functions
204 struct ls_prefix
*ls_prefix_new(struct ls_node_id adv
, struct prefix p
)
206 struct ls_prefix
*new;
208 if (adv
.origin
== UNKNOWN
)
211 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
218 void ls_prefix_del(struct ls_prefix
*pref
)
223 XFREE(MTYPE_LS_DB
, pref
);
227 int ls_prefix_same(struct ls_prefix
*p1
, struct ls_prefix
*p2
)
229 if ((p1
&& !p2
) || (!p1
&& p2
))
235 if (p1
->flags
!= p2
->flags
)
238 if (p1
->adv
.origin
!= p2
->adv
.origin
)
241 if (!memcmp(&p1
->adv
.id
, &p2
->adv
.id
, sizeof(struct ls_node_id
)))
244 /* Do we need to test individually each field, instead performing a
245 * global memcmp? There is a risk that an old value that is bit masked
246 * i.e. corresponding flag = 0, will result into a false negative
248 if (!memcmp(p1
, p2
, sizeof(struct ls_prefix
)))
255 * Link State Vertices management functions
257 struct ls_vertex
*ls_vertex_add(struct ls_ted
*ted
, struct ls_node
*node
)
259 struct ls_vertex
*new;
262 if ((ted
== NULL
) || (node
== NULL
))
265 /* set Key as the IPv4/Ipv6 Router ID or ISO System ID */
266 switch (node
->adv
.origin
) {
270 key
= ((uint64_t)ntohl(node
->adv
.id
.ip
.addr
.s_addr
))
275 memcpy(&key
, &node
->adv
.id
.iso
.sys_id
, ISO_SYS_ID_LEN
);
282 /* Check that key is valid */
286 /* Create Vertex and add it to the TED */
287 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_vertex
));
295 new->incoming_edges
= list_new();
296 new->incoming_edges
->cmp
= (int (*)(void *, void *))edge_cmp
;
297 new->outgoing_edges
= list_new();
298 new->outgoing_edges
->cmp
= (int (*)(void *, void *))edge_cmp
;
299 new->prefixes
= list_new();
300 new->prefixes
->cmp
= (int (*)(void *, void *))subnet_cmp
;
301 vertices_add(&ted
->vertices
, new);
306 void ls_vertex_del(struct ls_ted
*ted
, struct ls_vertex
*vertex
)
308 struct listnode
*node
, *nnode
;
309 struct ls_edge
*edge
;
310 struct ls_subnet
*subnet
;
315 /* Remove outgoing Edges and list */
316 for (ALL_LIST_ELEMENTS(vertex
->outgoing_edges
, node
, nnode
, edge
))
317 ls_edge_del_all(ted
, edge
);
318 list_delete(&vertex
->outgoing_edges
);
320 /* Disconnect incoming Edges and remove list */
321 for (ALL_LIST_ELEMENTS(vertex
->incoming_edges
, node
, nnode
, edge
)) {
322 ls_disconnect(vertex
, edge
, false);
323 if (edge
->source
== NULL
)
324 ls_edge_del_all(ted
, edge
);
326 list_delete(&vertex
->incoming_edges
);
328 /* Remove subnet and list */
329 for (ALL_LIST_ELEMENTS(vertex
->prefixes
, node
, nnode
, subnet
))
330 ls_subnet_del_all(ted
, subnet
);
331 list_delete(&vertex
->prefixes
);
333 /* Then remove Vertex from Link State Data Base and free memory */
334 vertices_del(&ted
->vertices
, vertex
);
335 XFREE(MTYPE_LS_DB
, vertex
);
339 void ls_vertex_del_all(struct ls_ted
*ted
, struct ls_vertex
*vertex
)
344 /* First remove associated Link State Node */
345 ls_node_del(vertex
->node
);
347 /* Then, Vertex itself */
348 ls_vertex_del(ted
, vertex
);
351 struct ls_vertex
*ls_vertex_update(struct ls_ted
*ted
, struct ls_node
*node
)
353 struct ls_vertex
*old
;
358 old
= ls_find_vertex_by_id(ted
, node
->adv
);
360 if (!ls_node_same(old
->node
, node
)) {
361 ls_node_del(old
->node
);
364 old
->status
= UPDATE
;
368 return ls_vertex_add(ted
, node
);
371 struct ls_vertex
*ls_find_vertex_by_key(struct ls_ted
*ted
, const uint64_t key
)
373 struct ls_vertex vertex
= {};
379 return vertices_find(&ted
->vertices
, &vertex
);
382 struct ls_vertex
*ls_find_vertex_by_id(struct ls_ted
*ted
,
383 struct ls_node_id nid
)
385 struct ls_vertex vertex
= {};
388 switch (nid
.origin
) {
393 ((uint64_t)ntohl(nid
.id
.ip
.addr
.s_addr
)) & 0xffffffff;
397 memcpy(&vertex
.key
, &nid
.id
.iso
.sys_id
, ISO_SYS_ID_LEN
);
403 return vertices_find(&ted
->vertices
, &vertex
);
406 int ls_vertex_same(struct ls_vertex
*v1
, struct ls_vertex
*v2
)
408 if ((v1
&& !v2
) || (!v1
&& v2
))
414 if (v1
->key
!= v2
->key
)
417 if (v1
->node
== v2
->node
)
420 return ls_node_same(v1
->node
, v2
->node
);
423 void ls_vertex_clean(struct ls_ted
*ted
, struct ls_vertex
*vertex
,
424 struct zclient
*zclient
)
426 struct listnode
*node
, *nnode
;
427 struct ls_edge
*edge
;
428 struct ls_subnet
*subnet
;
429 struct ls_message msg
;
431 /* Remove Orphan Edge ... */
432 for (ALL_LIST_ELEMENTS(vertex
->outgoing_edges
, node
, nnode
, edge
)) {
433 if (edge
->status
== ORPHAN
) {
435 edge
->status
= DELETE
;
436 ls_edge2msg(&msg
, edge
);
437 ls_send_msg(zclient
, &msg
, NULL
);
439 ls_edge_del_all(ted
, edge
);
442 for (ALL_LIST_ELEMENTS(vertex
->incoming_edges
, node
, nnode
, edge
)) {
443 if (edge
->status
== ORPHAN
) {
445 edge
->status
= DELETE
;
446 ls_edge2msg(&msg
, edge
);
447 ls_send_msg(zclient
, &msg
, NULL
);
449 ls_edge_del_all(ted
, edge
);
453 /* ... and Subnet from the Vertex */
454 for (ALL_LIST_ELEMENTS(vertex
->prefixes
, node
, nnode
, subnet
)) {
455 if (subnet
->status
== ORPHAN
) {
457 subnet
->status
= DELETE
;
458 ls_subnet2msg(&msg
, subnet
);
459 ls_send_msg(zclient
, &msg
, NULL
);
461 ls_subnet_del_all(ted
, subnet
);
467 * Link State Edges management functions
471 * This function allows to connect the Edge to the vertices present in the TED.
472 * A temporary vertex that corresponds to the source of this Edge i.e. the
473 * advertised router, is created if not found in the Data Base. If a Edge that
474 * corresponds to the reverse path is found, the Edge is attached to the
475 * destination vertex as destination and reverse Edge is attached to the source
478 * @param ted Link State Data Base
479 * @param edge Link State Edge to be attached
481 static void ls_edge_connect_to(struct ls_ted
*ted
, struct ls_edge
*edge
)
483 struct ls_vertex
*vertex
= NULL
;
484 struct ls_node
*node
;
486 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
488 /* First, search if there is a Vertex that correspond to the Node ID */
489 vertex
= ls_find_vertex_by_id(ted
, edge
->attributes
->adv
);
490 if (vertex
== NULL
) {
491 /* Create a new temporary Node & Vertex if not found */
492 node
= ls_node_new(edge
->attributes
->adv
, inaddr_any
,
494 vertex
= ls_vertex_add(ted
, node
);
496 /* and attach the edge as source to the vertex */
497 listnode_add_sort_nodup(vertex
->outgoing_edges
, edge
);
498 edge
->source
= vertex
;
500 /* Then search if there is a reverse Edge */
501 dst
= ls_find_edge_by_destination(ted
, edge
->attributes
);
502 /* attach the destination edge to the vertex */
504 listnode_add_sort_nodup(vertex
->incoming_edges
, dst
);
505 dst
->destination
= vertex
;
506 /* and destination vertex to this edge */
507 vertex
= dst
->source
;
508 listnode_add_sort_nodup(vertex
->incoming_edges
, edge
);
509 edge
->destination
= vertex
;
513 struct ls_edge
*ls_edge_add(struct ls_ted
*ted
,
514 struct ls_attributes
*attributes
)
519 if (attributes
== NULL
)
522 /* Key is the IPv4 local address */
523 if (!IPV4_NET0(attributes
->standard
.local
.s_addr
))
524 key
= ((uint64_t)ntohl(attributes
->standard
.local
.s_addr
))
526 /* or the IPv6 local address if IPv4 is not defined */
527 else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes
->standard
.local6
))
528 key
= (uint64_t)(attributes
->standard
.local6
.s6_addr32
[0]
530 | ((uint64_t)attributes
->standard
.local6
.s6_addr32
[1]
532 /* of local identifier if no IP addresses are defined */
533 else if (attributes
->standard
.local_id
!= 0)
535 (attributes
->standard
.local_id
& 0xffffffff)
536 | ((uint64_t)attributes
->standard
.remote_id
<< 32));
538 /* Check that key is valid */
542 /* Create Edge and add it to the TED */
543 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_edge
));
547 new->attributes
= attributes
;
551 edges_add(&ted
->edges
, new);
553 /* Finally, connect Edge to Vertices */
554 ls_edge_connect_to(ted
, new);
559 struct ls_edge
*ls_find_edge_by_key(struct ls_ted
*ted
, const uint64_t key
)
561 struct ls_edge edge
= {};
567 return edges_find(&ted
->edges
, &edge
);
570 struct ls_edge
*ls_find_edge_by_source(struct ls_ted
*ted
,
571 struct ls_attributes
*attributes
)
573 struct ls_edge edge
= {};
575 if (attributes
== NULL
)
579 /* Key is the IPv4 local address */
580 if (!IPV4_NET0(attributes
->standard
.local
.s_addr
))
581 edge
.key
= ((uint64_t)ntohl(attributes
->standard
.local
.s_addr
))
583 /* or the IPv6 local address if IPv4 is not defined */
584 else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes
->standard
.local6
))
585 edge
.key
= (uint64_t)(attributes
->standard
.local6
.s6_addr32
[0]
587 | ((uint64_t)attributes
->standard
.local6
.s6_addr32
[1]
589 /* of local identifier if no IP addresses are defined */
590 else if (attributes
->standard
.local_id
!= 0)
591 edge
.key
= (uint64_t)(
592 (attributes
->standard
.local_id
& 0xffffffff)
593 | ((uint64_t)attributes
->standard
.remote_id
<< 32));
598 return edges_find(&ted
->edges
, &edge
);
601 struct ls_edge
*ls_find_edge_by_destination(struct ls_ted
*ted
,
602 struct ls_attributes
*attributes
)
604 struct ls_edge edge
= {};
606 if (attributes
== NULL
)
610 /* Key is the IPv4 remote address */
611 if (!IPV4_NET0(attributes
->standard
.remote
.s_addr
))
612 edge
.key
= ((uint64_t)ntohl(attributes
->standard
.remote
.s_addr
))
614 /* or the IPv6 remote address if IPv4 is not defined */
615 else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes
->standard
.remote6
))
617 (uint64_t)(attributes
->standard
.remote6
.s6_addr32
[0]
619 | ((uint64_t)attributes
->standard
.remote6
.s6_addr32
[1]
621 /* of remote identifier if no IP addresses are defined */
622 else if (attributes
->standard
.remote_id
!= 0)
623 edge
.key
= (uint64_t)(
624 (attributes
->standard
.remote_id
& 0xffffffff)
625 | ((uint64_t)attributes
->standard
.local_id
<< 32));
630 return edges_find(&ted
->edges
, &edge
);
633 struct ls_edge
*ls_edge_update(struct ls_ted
*ted
,
634 struct ls_attributes
*attributes
)
638 if (attributes
== NULL
)
641 /* First, search for an existing Edge */
642 old
= ls_find_edge_by_source(ted
, attributes
);
644 /* Check if attributes are similar */
645 if (!ls_attributes_same(old
->attributes
, attributes
)) {
646 ls_attributes_del(old
->attributes
);
647 old
->attributes
= attributes
;
649 old
->status
= UPDATE
;
653 /* If not found, add new Edge from the attributes */
654 return ls_edge_add(ted
, attributes
);
657 int ls_edge_same(struct ls_edge
*e1
, struct ls_edge
*e2
)
659 if ((e1
&& !e2
) || (!e1
&& e2
))
665 if (e1
->key
!= e2
->key
)
668 if (e1
->attributes
== e2
->attributes
)
671 return ls_attributes_same(e1
->attributes
, e2
->attributes
);
674 void ls_edge_del(struct ls_ted
*ted
, struct ls_edge
*edge
)
679 /* Fist disconnect Edge from Vertices */
680 ls_disconnect_edge(edge
);
681 /* Then remove it from the Data Base */
682 edges_del(&ted
->edges
, edge
);
683 XFREE(MTYPE_LS_DB
, edge
);
686 void ls_edge_del_all(struct ls_ted
*ted
, struct ls_edge
*edge
)
691 /* Remove associated Link State Attributes */
692 ls_attributes_del(edge
->attributes
);
693 /* Then Edge itself */
694 ls_edge_del(ted
, edge
);
698 * Link State Subnet Management functions.
700 struct ls_subnet
*ls_subnet_add(struct ls_ted
*ted
,
701 struct ls_prefix
*ls_pref
)
703 struct ls_subnet
*new;
704 struct ls_vertex
*vertex
;
705 struct ls_node
*node
;
706 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
711 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_subnet
));
712 new->ls_pref
= ls_pref
;
713 new->key
= ls_pref
->pref
;
718 vertex
= ls_find_vertex_by_id(ted
, ls_pref
->adv
);
719 if (vertex
== NULL
) {
720 /* Create a new temporary Node & Vertex if not found */
721 node
= ls_node_new(ls_pref
->adv
, inaddr_any
, in6addr_any
);
722 vertex
= ls_vertex_add(ted
, node
);
724 /* And attach the subnet to the corresponding Vertex */
725 new->vertex
= vertex
;
726 listnode_add_sort_nodup(vertex
->prefixes
, new);
728 subnets_add(&ted
->subnets
, new);
733 struct ls_subnet
*ls_subnet_update(struct ls_ted
*ted
, struct ls_prefix
*pref
)
735 struct ls_subnet
*old
;
740 old
= ls_find_subnet(ted
, pref
->pref
);
742 if (!ls_prefix_same(old
->ls_pref
, pref
)) {
743 ls_prefix_del(old
->ls_pref
);
746 old
->status
= UPDATE
;
750 return ls_subnet_add(ted
, pref
);
753 int ls_subnet_same(struct ls_subnet
*s1
, struct ls_subnet
*s2
)
755 if ((s1
&& !s2
) || (!s1
&& s2
))
761 if (!prefix_same(&s1
->key
, &s2
->key
))
764 if (s1
->ls_pref
== s2
->ls_pref
)
767 return ls_prefix_same(s1
->ls_pref
, s2
->ls_pref
);
770 void ls_subnet_del(struct ls_ted
*ted
, struct ls_subnet
*subnet
)
775 /* First, disconnect Subnet from associated Vertex */
776 listnode_delete(subnet
->vertex
->prefixes
, subnet
);
777 /* Then delete Subnet */
778 subnets_del(&ted
->subnets
, subnet
);
779 XFREE(MTYPE_LS_DB
, subnet
);
782 void ls_subnet_del_all(struct ls_ted
*ted
, struct ls_subnet
*subnet
)
787 /* First, remove associated Link State Subnet */
788 ls_prefix_del(subnet
->ls_pref
);
789 /* Then, delete Subnet itself */
790 ls_subnet_del(ted
, subnet
);
793 struct ls_subnet
*ls_find_subnet(struct ls_ted
*ted
, const struct prefix prefix
)
795 struct ls_subnet subnet
= {};
798 return subnets_find(&ted
->subnets
, &subnet
);
802 * Link State TED management functions
804 struct ls_ted
*ls_ted_new(const uint32_t key
, const char *name
,
809 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_ted
));
813 /* Set basic information for this ted */
815 new->as_number
= as_number
;
816 strlcpy(new->name
, name
, MAX_NAME_LENGTH
);
818 /* Initialize the various RB tree */
819 vertices_init(&new->vertices
);
820 edges_init(&new->edges
);
821 subnets_init(&new->subnets
);
826 void ls_ted_del(struct ls_ted
*ted
)
831 /* Check that TED is empty */
832 if (vertices_count(&ted
->vertices
) || edges_count(&ted
->edges
)
833 || subnets_count(&ted
->subnets
))
836 /* Release RB Tree */
837 vertices_fini(&ted
->vertices
);
838 edges_fini(&ted
->edges
);
839 subnets_fini(&ted
->subnets
);
841 XFREE(MTYPE_LS_DB
, ted
);
845 void ls_ted_del_all(struct ls_ted
*ted
)
847 struct ls_vertex
*vertex
;
848 struct ls_edge
*edge
;
849 struct ls_subnet
*subnet
;
854 /* First remove Vertices, Edges and Subnets and associated Link State */
855 frr_each (vertices
, &ted
->vertices
, vertex
)
856 ls_vertex_del_all(ted
, vertex
);
857 frr_each (edges
, &ted
->edges
, edge
)
858 ls_edge_del_all(ted
, edge
);
859 frr_each (subnets
, &ted
->subnets
, subnet
)
860 ls_subnet_del_all(ted
, subnet
);
862 /* then remove TED itself */
866 void ls_ted_clean(struct ls_ted
*ted
)
868 struct ls_vertex
*vertex
;
869 struct ls_edge
*edge
;
870 struct ls_subnet
*subnet
;
875 /* First, start with Vertices */
876 frr_each (vertices
, &ted
->vertices
, vertex
)
877 if (vertex
->status
== ORPHAN
)
878 ls_vertex_del_all(ted
, vertex
);
881 frr_each (edges
, &ted
->edges
, edge
)
882 if (edge
->status
== ORPHAN
)
883 ls_edge_del_all(ted
, edge
);
886 frr_each (subnets
, &ted
->subnets
, subnet
)
887 if (subnet
->status
== ORPHAN
)
888 ls_subnet_del_all(ted
, subnet
);
892 void ls_connect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
894 if (vertex
== NULL
|| edge
== NULL
)
898 listnode_add_sort_nodup(vertex
->outgoing_edges
, edge
);
899 edge
->source
= vertex
;
901 listnode_add_sort_nodup(vertex
->incoming_edges
, edge
);
902 edge
->destination
= vertex
;
906 void ls_disconnect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
909 if (vertex
== NULL
|| edge
== NULL
)
913 listnode_delete(vertex
->outgoing_edges
, edge
);
916 listnode_delete(vertex
->incoming_edges
, edge
);
917 edge
->destination
= NULL
;
921 void ls_connect_vertices(struct ls_vertex
*src
, struct ls_vertex
*dst
,
922 struct ls_edge
*edge
)
928 edge
->destination
= dst
;
931 listnode_add_sort_nodup(src
->outgoing_edges
, edge
);
934 listnode_add_sort_nodup(dst
->incoming_edges
, edge
);
937 void ls_disconnect_edge(struct ls_edge
*edge
)
942 ls_disconnect(edge
->source
, edge
, true);
943 ls_disconnect(edge
->destination
, edge
, false);
945 /* Mark this Edge as ORPHAN for future cleanup */
946 edge
->status
= ORPHAN
;
950 * Link State Message management functions
953 int ls_register(struct zclient
*zclient
, bool server
)
958 rc
= zclient_register_opaque(zclient
, LINK_STATE_SYNC
);
960 rc
= zclient_register_opaque(zclient
, LINK_STATE_UPDATE
);
965 int ls_unregister(struct zclient
*zclient
, bool server
)
970 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_SYNC
);
972 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_UPDATE
);
977 int ls_request_sync(struct zclient
*zclient
)
982 /* Check buffer size */
983 if (STREAM_SIZE(zclient
->obuf
)
984 < (ZEBRA_HEADER_SIZE
+ 3 * sizeof(uint32_t)))
990 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
992 /* Set type and flags */
993 stream_putl(s
, LINK_STATE_SYNC
);
994 stream_putw(s
, flags
);
995 /* Send destination client info */
996 stream_putc(s
, zclient
->redist_default
);
997 stream_putw(s
, zclient
->instance
);
998 stream_putl(s
, zclient
->session_id
);
1000 /* Put length into the header at the start of the stream. */
1001 stream_putw_at(s
, 0, stream_get_endp(s
));
1003 return zclient_send_message(zclient
);
1006 static struct ls_node
*ls_parse_node(struct stream
*s
)
1008 struct ls_node
*node
;
1011 node
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
1015 STREAM_GET(&node
->adv
, s
, sizeof(struct ls_node_id
));
1016 STREAM_GETW(s
, node
->flags
);
1017 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1018 STREAM_GETC(s
, len
);
1019 STREAM_GET(node
->name
, s
, len
);
1021 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1022 node
->router_id
.s_addr
= stream_get_ipv4(s
);
1023 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1024 STREAM_GET(&node
->router6_id
, s
, IPV6_MAX_BYTELEN
);
1025 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1026 STREAM_GETC(s
, node
->node_flag
);
1027 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1028 STREAM_GETC(s
, node
->type
);
1029 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1030 STREAM_GETL(s
, node
->as_number
);
1031 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1032 STREAM_GETL(s
, node
->srgb
.lower_bound
);
1033 STREAM_GETL(s
, node
->srgb
.range_size
);
1034 STREAM_GETC(s
, node
->srgb
.flag
);
1035 STREAM_GET(node
->algo
, s
, 2);
1037 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1038 STREAM_GETL(s
, node
->srlb
.lower_bound
);
1039 STREAM_GETL(s
, node
->srlb
.range_size
);
1041 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1042 STREAM_GETC(s
, node
->msd
);
1047 zlog_err("LS(%s): Could not parse Link State Node. Abort!", __func__
);
1048 XFREE(MTYPE_LS_DB
, node
);
1052 static struct ls_attributes
*ls_parse_attributes(struct stream
*s
)
1054 struct ls_attributes
*attr
;
1057 attr
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
1062 STREAM_GET(&attr
->adv
, s
, sizeof(struct ls_node_id
));
1063 STREAM_GETL(s
, attr
->flags
);
1064 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1065 STREAM_GETC(s
, len
);
1066 STREAM_GET(attr
->name
, s
, len
);
1068 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1069 STREAM_GETL(s
, attr
->metric
);
1070 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1071 STREAM_GETL(s
, attr
->standard
.te_metric
);
1072 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1073 STREAM_GETL(s
, attr
->standard
.admin_group
);
1074 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1075 attr
->standard
.local
.s_addr
= stream_get_ipv4(s
);
1076 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1077 attr
->standard
.remote
.s_addr
= stream_get_ipv4(s
);
1078 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1079 STREAM_GET(&attr
->standard
.local6
, s
, IPV6_MAX_BYTELEN
);
1080 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1081 STREAM_GET(&attr
->standard
.remote6
, s
, IPV6_MAX_BYTELEN
);
1082 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1083 STREAM_GETL(s
, attr
->standard
.local_id
);
1084 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1085 STREAM_GETL(s
, attr
->standard
.remote_id
);
1086 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1087 STREAM_GETF(s
, attr
->standard
.max_bw
);
1088 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1089 STREAM_GETF(s
, attr
->standard
.max_rsv_bw
);
1090 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1091 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1092 STREAM_GETF(s
, attr
->standard
.unrsv_bw
[len
]);
1093 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1094 STREAM_GETL(s
, attr
->standard
.remote_as
);
1095 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1096 attr
->standard
.remote_addr
.s_addr
= stream_get_ipv4(s
);
1097 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1098 STREAM_GET(&attr
->standard
.remote_addr6
, s
, IPV6_MAX_BYTELEN
);
1099 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1100 STREAM_GETL(s
, attr
->extended
.delay
);
1101 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1102 STREAM_GETL(s
, attr
->extended
.min_delay
);
1103 STREAM_GETL(s
, attr
->extended
.max_delay
);
1105 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1106 STREAM_GETL(s
, attr
->extended
.jitter
);
1107 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1108 STREAM_GETL(s
, attr
->extended
.pkt_loss
);
1109 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1110 STREAM_GETF(s
, attr
->extended
.ava_bw
);
1111 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1112 STREAM_GETF(s
, attr
->extended
.rsv_bw
);
1113 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1114 STREAM_GETF(s
, attr
->extended
.used_bw
);
1115 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1116 STREAM_GETL(s
, attr
->adj_sid
[0].sid
);
1117 STREAM_GETC(s
, attr
->adj_sid
[0].flags
);
1118 STREAM_GETC(s
, attr
->adj_sid
[0].weight
);
1119 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1120 STREAM_GET(attr
->adj_sid
[0].neighbor
.sysid
, s
,
1122 else if (attr
->adv
.origin
== OSPFv2
)
1123 attr
->adj_sid
[0].neighbor
.addr
.s_addr
=
1126 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1127 STREAM_GETL(s
, attr
->adj_sid
[1].sid
);
1128 STREAM_GETC(s
, attr
->adj_sid
[1].flags
);
1129 STREAM_GETC(s
, attr
->adj_sid
[1].weight
);
1130 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1131 STREAM_GET(attr
->adj_sid
[1].neighbor
.sysid
, s
,
1133 else if (attr
->adv
.origin
== OSPFv2
)
1134 attr
->adj_sid
[1].neighbor
.addr
.s_addr
=
1137 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1138 STREAM_GETC(s
, len
);
1139 attr
->srlgs
= XCALLOC(MTYPE_LS_DB
, len
*sizeof(uint32_t));
1140 attr
->srlg_len
= len
;
1141 for (len
= 0; len
< attr
->srlg_len
; len
++)
1142 STREAM_GETL(s
, attr
->srlgs
[len
]);
1148 zlog_err("LS(%s): Could not parse Link State Attributes. Abort!",
1150 /* Clean memory allocation */
1151 if (attr
->srlgs
!= NULL
)
1152 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
1153 XFREE(MTYPE_LS_DB
, attr
);
1158 static struct ls_prefix
*ls_parse_prefix(struct stream
*s
)
1160 struct ls_prefix
*ls_pref
;
1163 ls_pref
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_prefix
));
1164 if (ls_pref
== NULL
)
1167 STREAM_GET(&ls_pref
->adv
, s
, sizeof(struct ls_node_id
));
1168 STREAM_GETW(s
, ls_pref
->flags
);
1169 STREAM_GETC(s
, ls_pref
->pref
.family
);
1170 STREAM_GETW(s
, ls_pref
->pref
.prefixlen
);
1171 len
= prefix_blen(&ls_pref
->pref
);
1172 STREAM_GET(&ls_pref
->pref
.u
.prefix
, s
, len
);
1173 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1174 STREAM_GETC(s
, ls_pref
->igp_flag
);
1175 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1176 STREAM_GETL(s
, ls_pref
->route_tag
);
1177 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1178 STREAM_GETQ(s
, ls_pref
->extended_tag
);
1179 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1180 STREAM_GETL(s
, ls_pref
->metric
);
1181 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1182 STREAM_GETL(s
, ls_pref
->sr
.sid
);
1183 STREAM_GETC(s
, ls_pref
->sr
.sid_flag
);
1184 STREAM_GETC(s
, ls_pref
->sr
.algo
);
1190 zlog_err("LS(%s): Could not parse Link State Prefix. Abort!", __func__
);
1191 XFREE(MTYPE_LS_DB
, ls_pref
);
1195 struct ls_message
*ls_parse_msg(struct stream
*s
)
1197 struct ls_message
*msg
;
1199 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1203 /* Read LS Message header */
1204 STREAM_GETC(s
, msg
->event
);
1205 STREAM_GETC(s
, msg
->type
);
1206 STREAM_GET(&msg
->remote_id
, s
, sizeof(struct ls_node_id
));
1208 /* Read Message Payload */
1209 switch (msg
->type
) {
1210 case LS_MSG_TYPE_NODE
:
1211 msg
->data
.node
= ls_parse_node(s
);
1213 case LS_MSG_TYPE_ATTRIBUTES
:
1214 msg
->data
.attr
= ls_parse_attributes(s
);
1216 case LS_MSG_TYPE_PREFIX
:
1217 msg
->data
.prefix
= ls_parse_prefix(s
);
1220 zlog_err("Unsupported Payload");
1221 goto stream_failure
;
1224 if (msg
->data
.node
== NULL
|| msg
->data
.attr
== NULL
1225 || msg
->data
.prefix
== NULL
)
1226 goto stream_failure
;
1231 zlog_err("LS(%s): Could not parse LS message. Abort!", __func__
);
1232 XFREE(MTYPE_LS_DB
, msg
);
1236 static int ls_format_node(struct stream
*s
, struct ls_node
*node
)
1240 /* Push Advertise node information first */
1241 stream_put(s
, &node
->adv
, sizeof(struct ls_node_id
));
1243 /* Push Flags & Origin then Node information if there are present */
1244 stream_putw(s
, node
->flags
);
1245 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1246 len
= strlen(node
->name
);
1247 stream_putc(s
, len
+ 1);
1248 stream_put(s
, node
->name
, len
);
1249 stream_putc(s
, '\0');
1251 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1252 stream_put_ipv4(s
, node
->router_id
.s_addr
);
1253 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1254 stream_put(s
, &node
->router6_id
, IPV6_MAX_BYTELEN
);
1255 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1256 stream_putc(s
, node
->node_flag
);
1257 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1258 stream_putc(s
, node
->type
);
1259 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1260 stream_putl(s
, node
->as_number
);
1261 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1262 stream_putl(s
, node
->srgb
.lower_bound
);
1263 stream_putl(s
, node
->srgb
.range_size
);
1264 stream_putc(s
, node
->srgb
.flag
);
1265 stream_put(s
, node
->algo
, 2);
1267 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1268 stream_putl(s
, node
->srlb
.lower_bound
);
1269 stream_putl(s
, node
->srlb
.range_size
);
1271 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1272 stream_putc(s
, node
->msd
);
1277 static int ls_format_attributes(struct stream
*s
, struct ls_attributes
*attr
)
1281 /* Push Advertise node information first */
1282 stream_put(s
, &attr
->adv
, sizeof(struct ls_node_id
));
1284 /* Push Flags & Origin then LS attributes if there are present */
1285 stream_putl(s
, attr
->flags
);
1286 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1287 len
= strlen(attr
->name
);
1288 stream_putc(s
, len
+ 1);
1289 stream_put(s
, attr
->name
, len
);
1290 stream_putc(s
, '\0');
1292 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1293 stream_putl(s
, attr
->metric
);
1294 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1295 stream_putl(s
, attr
->standard
.te_metric
);
1296 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1297 stream_putl(s
, attr
->standard
.admin_group
);
1298 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1299 stream_put_ipv4(s
, attr
->standard
.local
.s_addr
);
1300 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1301 stream_put_ipv4(s
, attr
->standard
.remote
.s_addr
);
1302 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1303 stream_put(s
, &attr
->standard
.local6
, IPV6_MAX_BYTELEN
);
1304 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1305 stream_put(s
, &attr
->standard
.remote6
, IPV6_MAX_BYTELEN
);
1306 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1307 stream_putl(s
, attr
->standard
.local_id
);
1308 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1309 stream_putl(s
, attr
->standard
.remote_id
);
1310 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1311 stream_putf(s
, attr
->standard
.max_bw
);
1312 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1313 stream_putf(s
, attr
->standard
.max_rsv_bw
);
1314 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1315 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1316 stream_putf(s
, attr
->standard
.unrsv_bw
[len
]);
1317 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1318 stream_putl(s
, attr
->standard
.remote_as
);
1319 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1320 stream_put_ipv4(s
, attr
->standard
.remote_addr
.s_addr
);
1321 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1322 stream_put(s
, &attr
->standard
.remote_addr6
, IPV6_MAX_BYTELEN
);
1323 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1324 stream_putl(s
, attr
->extended
.delay
);
1325 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1326 stream_putl(s
, attr
->extended
.min_delay
);
1327 stream_putl(s
, attr
->extended
.max_delay
);
1329 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1330 stream_putl(s
, attr
->extended
.jitter
);
1331 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1332 stream_putl(s
, attr
->extended
.pkt_loss
);
1333 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1334 stream_putf(s
, attr
->extended
.ava_bw
);
1335 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1336 stream_putf(s
, attr
->extended
.rsv_bw
);
1337 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1338 stream_putf(s
, attr
->extended
.used_bw
);
1339 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1340 stream_putl(s
, attr
->adj_sid
[0].sid
);
1341 stream_putc(s
, attr
->adj_sid
[0].flags
);
1342 stream_putc(s
, attr
->adj_sid
[0].weight
);
1343 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1344 stream_put(s
, attr
->adj_sid
[0].neighbor
.sysid
,
1346 else if (attr
->adv
.origin
== OSPFv2
)
1348 attr
->adj_sid
[0].neighbor
.addr
.s_addr
);
1350 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1351 stream_putl(s
, attr
->adj_sid
[1].sid
);
1352 stream_putc(s
, attr
->adj_sid
[1].flags
);
1353 stream_putc(s
, attr
->adj_sid
[1].weight
);
1354 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1355 stream_put(s
, attr
->adj_sid
[1].neighbor
.sysid
,
1357 else if (attr
->adv
.origin
== OSPFv2
)
1359 attr
->adj_sid
[1].neighbor
.addr
.s_addr
);
1361 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1362 stream_putc(s
, attr
->srlg_len
);
1363 for (len
= 0; len
< attr
->srlg_len
; len
++)
1364 stream_putl(s
, attr
->srlgs
[len
]);
1370 static int ls_format_prefix(struct stream
*s
, struct ls_prefix
*ls_pref
)
1374 /* Push Advertise node information first */
1375 stream_put(s
, &ls_pref
->adv
, sizeof(struct ls_node_id
));
1377 /* Push Flags, Origin & Prefix then information if there are present */
1378 stream_putw(s
, ls_pref
->flags
);
1379 stream_putc(s
, ls_pref
->pref
.family
);
1380 stream_putw(s
, ls_pref
->pref
.prefixlen
);
1381 len
= prefix_blen(&ls_pref
->pref
);
1382 stream_put(s
, &ls_pref
->pref
.u
.prefix
, len
);
1383 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1384 stream_putc(s
, ls_pref
->igp_flag
);
1385 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1386 stream_putl(s
, ls_pref
->route_tag
);
1387 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1388 stream_putq(s
, ls_pref
->extended_tag
);
1389 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1390 stream_putl(s
, ls_pref
->metric
);
1391 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1392 stream_putl(s
, ls_pref
->sr
.sid
);
1393 stream_putc(s
, ls_pref
->sr
.sid_flag
);
1394 stream_putc(s
, ls_pref
->sr
.algo
);
1400 static int ls_format_msg(struct stream
*s
, struct ls_message
*msg
)
1403 /* Prepare Link State header */
1404 stream_putc(s
, msg
->event
);
1405 stream_putc(s
, msg
->type
);
1406 stream_put(s
, &msg
->remote_id
, sizeof(struct ls_node_id
));
1408 /* Add Message Payload */
1409 switch (msg
->type
) {
1410 case LS_MSG_TYPE_NODE
:
1411 return ls_format_node(s
, msg
->data
.node
);
1412 case LS_MSG_TYPE_ATTRIBUTES
:
1413 return ls_format_attributes(s
, msg
->data
.attr
);
1414 case LS_MSG_TYPE_PREFIX
:
1415 return ls_format_prefix(s
, msg
->data
.prefix
);
1417 zlog_warn("Unsupported Payload");
1424 int ls_send_msg(struct zclient
*zclient
, struct ls_message
*msg
,
1425 struct zapi_opaque_reg_info
*dst
)
1430 /* Check if we have a valid message */
1431 if (msg
->event
== LS_MSG_EVENT_UNDEF
)
1434 /* Check buffer size */
1435 if (STREAM_SIZE(zclient
->obuf
) <
1436 (ZEBRA_HEADER_SIZE
+ sizeof(uint32_t) + sizeof(msg
)))
1442 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
1444 /* Set sub-type, flags and destination for unicast message */
1445 stream_putl(s
, LINK_STATE_UPDATE
);
1447 SET_FLAG(flags
, ZAPI_OPAQUE_FLAG_UNICAST
);
1448 stream_putw(s
, flags
);
1449 /* Send destination client info */
1450 stream_putc(s
, dst
->proto
);
1451 stream_putw(s
, dst
->instance
);
1452 stream_putl(s
, dst
->session_id
);
1454 stream_putw(s
, flags
);
1457 /* Format Link State message */
1458 if (ls_format_msg(s
, msg
) < 0) {
1463 /* Put length into the header at the start of the stream. */
1464 stream_putw_at(s
, 0, stream_get_endp(s
));
1466 return zclient_send_message(zclient
);
1469 struct ls_message
*ls_vertex2msg(struct ls_message
*msg
,
1470 struct ls_vertex
*vertex
)
1472 /* Allocate space if needed */
1474 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1476 memset(msg
, 0, sizeof(*msg
));
1478 msg
->type
= LS_MSG_TYPE_NODE
;
1479 switch (vertex
->status
) {
1481 msg
->event
= LS_MSG_EVENT_ADD
;
1484 msg
->event
= LS_MSG_EVENT_UPDATE
;
1487 msg
->event
= LS_MSG_EVENT_DELETE
;
1490 msg
->event
= LS_MSG_EVENT_SYNC
;
1493 msg
->event
= LS_MSG_EVENT_UNDEF
;
1496 msg
->data
.node
= vertex
->node
;
1497 msg
->remote_id
.origin
= UNKNOWN
;
1502 struct ls_message
*ls_edge2msg(struct ls_message
*msg
, struct ls_edge
*edge
)
1504 /* Allocate space if needed */
1506 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1508 memset(msg
, 0, sizeof(*msg
));
1510 msg
->type
= LS_MSG_TYPE_ATTRIBUTES
;
1511 switch (edge
->status
) {
1513 msg
->event
= LS_MSG_EVENT_ADD
;
1516 msg
->event
= LS_MSG_EVENT_UPDATE
;
1519 msg
->event
= LS_MSG_EVENT_DELETE
;
1522 msg
->event
= LS_MSG_EVENT_SYNC
;
1525 msg
->event
= LS_MSG_EVENT_UNDEF
;
1528 msg
->data
.attr
= edge
->attributes
;
1529 if (edge
->destination
!= NULL
)
1530 msg
->remote_id
= edge
->destination
->node
->adv
;
1532 msg
->remote_id
.origin
= UNKNOWN
;
1537 struct ls_message
*ls_subnet2msg(struct ls_message
*msg
,
1538 struct ls_subnet
*subnet
)
1540 /* Allocate space if needed */
1542 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1544 memset(msg
, 0, sizeof(*msg
));
1546 msg
->type
= LS_MSG_TYPE_PREFIX
;
1547 switch (subnet
->status
) {
1549 msg
->event
= LS_MSG_EVENT_ADD
;
1552 msg
->event
= LS_MSG_EVENT_UPDATE
;
1555 msg
->event
= LS_MSG_EVENT_DELETE
;
1558 msg
->event
= LS_MSG_EVENT_SYNC
;
1561 msg
->event
= LS_MSG_EVENT_UNDEF
;
1564 msg
->data
.prefix
= subnet
->ls_pref
;
1565 msg
->remote_id
.origin
= UNKNOWN
;
1570 struct ls_vertex
*ls_msg2vertex(struct ls_ted
*ted
, struct ls_message
*msg
,
1573 struct ls_node
*node
= (struct ls_node
*)msg
->data
.node
;
1574 struct ls_vertex
*vertex
= NULL
;
1576 switch (msg
->event
) {
1577 case LS_MSG_EVENT_SYNC
:
1578 vertex
= ls_vertex_add(ted
, node
);
1580 vertex
->status
= SYNC
;
1582 case LS_MSG_EVENT_ADD
:
1583 vertex
= ls_vertex_add(ted
, node
);
1585 vertex
->status
= NEW
;
1587 case LS_MSG_EVENT_UPDATE
:
1588 vertex
= ls_vertex_update(ted
, node
);
1590 vertex
->status
= UPDATE
;
1592 case LS_MSG_EVENT_DELETE
:
1593 vertex
= ls_find_vertex_by_id(ted
, node
->adv
);
1596 ls_vertex_del_all(ted
, vertex
);
1598 vertex
->status
= DELETE
;
1609 struct ls_edge
*ls_msg2edge(struct ls_ted
*ted
, struct ls_message
*msg
,
1612 struct ls_attributes
*attr
= (struct ls_attributes
*)msg
->data
.attr
;
1613 struct ls_edge
*edge
= NULL
;
1615 switch (msg
->event
) {
1616 case LS_MSG_EVENT_SYNC
:
1617 edge
= ls_edge_add(ted
, attr
);
1619 edge
->status
= SYNC
;
1621 case LS_MSG_EVENT_ADD
:
1622 edge
= ls_edge_add(ted
, attr
);
1626 case LS_MSG_EVENT_UPDATE
:
1627 edge
= ls_edge_update(ted
, attr
);
1629 edge
->status
= UPDATE
;
1631 case LS_MSG_EVENT_DELETE
:
1632 edge
= ls_find_edge_by_source(ted
, attr
);
1635 ls_edge_del_all(ted
, edge
);
1637 edge
->status
= DELETE
;
1648 struct ls_subnet
*ls_msg2subnet(struct ls_ted
*ted
, struct ls_message
*msg
,
1651 struct ls_prefix
*pref
= (struct ls_prefix
*)msg
->data
.prefix
;
1652 struct ls_subnet
*subnet
= NULL
;
1654 switch (msg
->event
) {
1655 case LS_MSG_EVENT_SYNC
:
1656 subnet
= ls_subnet_add(ted
, pref
);
1658 subnet
->status
= SYNC
;
1660 case LS_MSG_EVENT_ADD
:
1661 subnet
= ls_subnet_add(ted
, pref
);
1663 subnet
->status
= NEW
;
1665 case LS_MSG_EVENT_UPDATE
:
1666 subnet
= ls_subnet_update(ted
, pref
);
1668 subnet
->status
= UPDATE
;
1670 case LS_MSG_EVENT_DELETE
:
1671 subnet
= ls_find_subnet(ted
, pref
->pref
);
1674 ls_subnet_del_all(ted
, subnet
);
1676 subnet
->status
= DELETE
;
1687 struct ls_element
*ls_msg2ted(struct ls_ted
*ted
, struct ls_message
*msg
,
1690 struct ls_element
*lse
= NULL
;
1692 switch (msg
->type
) {
1693 case LS_MSG_TYPE_NODE
:
1694 lse
= (struct ls_element
*)ls_msg2vertex(ted
, msg
, delete);
1696 case LS_MSG_TYPE_ATTRIBUTES
:
1697 lse
= (struct ls_element
*)ls_msg2edge(ted
, msg
, delete);
1699 case LS_MSG_TYPE_PREFIX
:
1700 lse
= (struct ls_element
*)ls_msg2subnet(ted
, msg
, delete);
1710 struct ls_element
*ls_stream2ted(struct ls_ted
*ted
, struct stream
*s
,
1713 struct ls_message
*msg
;
1714 struct ls_element
*lse
= NULL
;
1716 msg
= ls_parse_msg(s
);
1718 lse
= ls_msg2ted(ted
, msg
, delete);
1725 void ls_delete_msg(struct ls_message
*msg
)
1730 XFREE(MTYPE_LS_DB
, msg
);
1733 int ls_sync_ted(struct ls_ted
*ted
, struct zclient
*zclient
,
1734 struct zapi_opaque_reg_info
*dst
)
1736 struct ls_vertex
*vertex
;
1737 struct ls_edge
*edge
;
1738 struct ls_subnet
*subnet
;
1739 struct ls_message msg
;
1741 /* Loop TED, start sending Node, then Attributes and finally Prefix */
1742 frr_each(vertices
, &ted
->vertices
, vertex
) {
1743 ls_vertex2msg(&msg
, vertex
);
1744 ls_send_msg(zclient
, &msg
, dst
);
1746 frr_each(edges
, &ted
->edges
, edge
) {
1747 ls_edge2msg(&msg
, edge
);
1748 ls_send_msg(zclient
, &msg
, dst
);
1750 frr_each(subnets
, &ted
->subnets
, subnet
) {
1751 ls_subnet2msg(&msg
, subnet
);
1752 ls_send_msg(zclient
, &msg
, dst
);
1758 * Link State Show functions
1760 static const char *const origin2txt
[] = {
1769 static const char *const type2txt
[] = {
1778 static const char *const status2txt
[] = {
1787 static const char *ls_node_id_to_text(struct ls_node_id lnid
, char *str
,
1790 if (lnid
.origin
== ISIS_L1
|| lnid
.origin
== ISIS_L2
) {
1793 id
= lnid
.id
.iso
.sys_id
;
1794 snprintfrr(str
, size
, "%02x%02x.%02x%02x.%02x%02x", id
[0],
1795 id
[1], id
[2], id
[3], id
[4], id
[5]);
1797 snprintfrr(str
, size
, "%pI4", &lnid
.id
.ip
.addr
);
1802 static void ls_show_vertex_vty(struct ls_vertex
*vertex
, struct vty
*vty
,
1805 struct listnode
*node
;
1806 struct ls_node
*lsn
;
1807 struct ls_edge
*edge
;
1808 struct ls_subnet
*subnet
;
1818 sbuf_init(&sbuf
, NULL
, 0);
1820 sbuf_push(&sbuf
, 2, "Vertex (%" PRIu64
"): %s", vertex
->key
, lsn
->name
);
1821 sbuf_push(&sbuf
, 0, "\tRouter Id: %pI4", &lsn
->router_id
);
1822 sbuf_push(&sbuf
, 0, "\tOrigin: %s", origin2txt
[lsn
->adv
.origin
]);
1823 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[vertex
->status
]);
1827 "\t%d Outgoing Edges, %d Incoming Edges, %d Subnets\n",
1828 listcount(vertex
->outgoing_edges
),
1829 listcount(vertex
->incoming_edges
),
1830 listcount(vertex
->prefixes
));
1834 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
1835 sbuf_push(&sbuf
, 4, "Type: %s\n", type2txt
[lsn
->type
]);
1836 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
1837 sbuf_push(&sbuf
, 4, "AS number: %u\n", lsn
->as_number
);
1838 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
1839 sbuf_push(&sbuf
, 4, "Segment Routing Capabilities:\n");
1840 upper
= lsn
->srgb
.lower_bound
+ lsn
->srgb
.range_size
- 1;
1841 sbuf_push(&sbuf
, 8, "SRGB: [%d/%d]", lsn
->srgb
.lower_bound
,
1843 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
1844 upper
= lsn
->srlb
.lower_bound
+ lsn
->srlb
.range_size
1846 sbuf_push(&sbuf
, 0, "\tSRLB: [%d/%d]",
1847 lsn
->srlb
.lower_bound
, upper
);
1849 sbuf_push(&sbuf
, 0, "\tAlgo: ");
1850 for (int i
= 0; i
< 2; i
++) {
1851 if (lsn
->algo
[i
] == 255)
1855 lsn
->algo
[i
] == 0 ? "SPF " : "S-SPF ");
1857 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
1858 sbuf_push(&sbuf
, 0, "\tMSD: %d", lsn
->msd
);
1859 sbuf_push(&sbuf
, 0, "\n");
1862 sbuf_push(&sbuf
, 4, "Outgoing Edges: %d\n",
1863 listcount(vertex
->outgoing_edges
));
1864 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, node
, edge
)) {
1865 if (edge
->destination
) {
1866 lsn
= edge
->destination
->node
;
1867 sbuf_push(&sbuf
, 6, "To:\t%s(%pI4)", lsn
->name
,
1870 sbuf_push(&sbuf
, 6, "To:\t- (0.0.0.0)");
1872 sbuf_push(&sbuf
, 0, "\tLocal: %pI4\tRemote: %pI4\n",
1873 &edge
->attributes
->standard
.local
,
1874 &edge
->attributes
->standard
.remote
);
1877 sbuf_push(&sbuf
, 4, "Incoming Edges: %d\n",
1878 listcount(vertex
->incoming_edges
));
1879 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, node
, edge
)) {
1881 lsn
= edge
->source
->node
;
1882 sbuf_push(&sbuf
, 6, "From:\t%s(%pI4)", lsn
->name
,
1885 sbuf_push(&sbuf
, 6, "From:\t- (0.0.0.0)");
1887 sbuf_push(&sbuf
, 0, "\tRemote: %pI4\tLocal: %pI4\n",
1888 &edge
->attributes
->standard
.local
,
1889 &edge
->attributes
->standard
.remote
);
1892 sbuf_push(&sbuf
, 4, "Subnets: %d\n", listcount(vertex
->prefixes
));
1893 for (ALL_LIST_ELEMENTS_RO(vertex
->prefixes
, node
, subnet
))
1894 sbuf_push(&sbuf
, 6, "Prefix:\t%pFX\n", &subnet
->key
);
1897 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
1901 static void ls_show_vertex_json(struct ls_vertex
*vertex
,
1902 struct json_object
*json
)
1904 struct ls_node
*lsn
;
1905 json_object
*jsr
, *jalgo
, *jobj
;
1906 char buf
[INET6_BUFSIZ
];
1914 json_object_int_add(json
, "vertex-id", vertex
->key
);
1915 json_object_string_add(json
, "status", status2txt
[vertex
->status
]);
1916 json_object_string_add(json
, "origin", origin2txt
[lsn
->adv
.origin
]);
1917 if (CHECK_FLAG(lsn
->flags
, LS_NODE_NAME
))
1918 json_object_string_add(json
, "name", lsn
->name
);
1919 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID
)) {
1920 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &lsn
->router_id
);
1921 json_object_string_add(json
, "router-id", buf
);
1923 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID6
)) {
1924 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &lsn
->router6_id
);
1925 json_object_string_add(json
, "router-id-v6", buf
);
1927 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
1928 json_object_string_add(json
, "vertex-type",
1929 type2txt
[lsn
->type
]);
1930 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
1931 json_object_int_add(json
, "asn", lsn
->as_number
);
1932 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
1933 jsr
= json_object_new_object();
1934 json_object_object_add(json
, "segment-routing", jsr
);
1935 json_object_int_add(jsr
, "srgb-size", lsn
->srgb
.range_size
);
1936 json_object_int_add(jsr
, "srgb-lower", lsn
->srgb
.lower_bound
);
1937 jalgo
= json_object_new_array();
1938 json_object_object_add(jsr
, "algorithms", jalgo
);
1939 for (int i
= 0; i
< 2; i
++) {
1940 if (lsn
->algo
[i
] == 255)
1942 jobj
= json_object_new_object();
1944 snprintfrr(buf
, 2, "%u", i
);
1945 json_object_string_add(
1946 jobj
, buf
, lsn
->algo
[i
] == 0 ? "SPF" : "S-SPF");
1947 json_object_array_add(jalgo
, jobj
);
1949 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
1950 json_object_int_add(jsr
, "srlb-size",
1951 lsn
->srlb
.range_size
);
1952 json_object_int_add(jsr
, "srlb-lower",
1953 lsn
->srlb
.lower_bound
);
1955 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
1956 json_object_int_add(jsr
, "msd", lsn
->msd
);
1960 void ls_show_vertex(struct ls_vertex
*vertex
, struct vty
*vty
,
1961 struct json_object
*json
, bool verbose
)
1964 ls_show_vertex_json(vertex
, json
);
1966 ls_show_vertex_vty(vertex
, vty
, verbose
);
1969 void ls_show_vertices(struct ls_ted
*ted
, struct vty
*vty
,
1970 struct json_object
*json
, bool verbose
)
1972 struct ls_vertex
*vertex
;
1973 json_object
*jnodes
, *jnode
;
1976 jnodes
= json_object_new_array();
1977 json_object_object_add(json
, "vertices", jnodes
);
1978 frr_each (vertices
, &ted
->vertices
, vertex
) {
1979 jnode
= json_object_new_object();
1980 ls_show_vertex(vertex
, NULL
, jnode
, verbose
);
1981 json_object_array_add(jnodes
, jnode
);
1984 frr_each (vertices
, &ted
->vertices
, vertex
)
1985 ls_show_vertex(vertex
, vty
, NULL
, verbose
);
1989 static void ls_show_edge_vty(struct ls_edge
*edge
, struct vty
*vty
,
1992 struct ls_attributes
*attr
;
1994 char buf
[INET6_BUFSIZ
];
1996 attr
= edge
->attributes
;
1997 sbuf_init(&sbuf
, NULL
, 0);
1999 sbuf_push(&sbuf
, 2, "Edge (%" PRIu64
"): ", edge
->key
);
2000 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
2001 sbuf_push(&sbuf
, 0, "%pI4", &attr
->standard
.local
);
2002 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
2003 sbuf_push(&sbuf
, 0, "%pI6", &attr
->standard
.local6
);
2005 sbuf_push(&sbuf
, 0, "%u/%u", attr
->standard
.local_id
,
2006 attr
->standard
.remote_id
);
2007 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
2008 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
2009 sbuf_push(&sbuf
, 0, "\tMetric: %u", attr
->metric
);
2010 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[edge
->status
]);
2015 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[attr
->adv
.origin
]);
2016 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2017 sbuf_push(&sbuf
, 4, "Name: %s\n", attr
->name
);
2018 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2019 sbuf_push(&sbuf
, 4, "TE Metric: %u\n",
2020 attr
->standard
.te_metric
);
2021 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2022 sbuf_push(&sbuf
, 4, "Admin Group: 0x%x\n",
2023 attr
->standard
.admin_group
);
2024 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
2025 sbuf_push(&sbuf
, 4, "Local IPv4 address: %pI4\n",
2026 &attr
->standard
.local
);
2027 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
2028 sbuf_push(&sbuf
, 4, "Remote IPv4 address: %pI4\n",
2029 &attr
->standard
.remote
);
2030 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
2031 sbuf_push(&sbuf
, 4, "Local IPv6 address: %pI6\n",
2032 &attr
->standard
.local6
);
2033 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
2034 sbuf_push(&sbuf
, 4, "Remote IPv6 address: %pI6\n",
2035 &attr
->standard
.remote6
);
2036 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2037 sbuf_push(&sbuf
, 4, "Local Identifier: %u\n",
2038 attr
->standard
.local_id
);
2039 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2040 sbuf_push(&sbuf
, 4, "Remote Identifier: %u\n",
2041 attr
->standard
.remote_id
);
2042 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2043 sbuf_push(&sbuf
, 4, "Maximum Bandwidth: %g (Bytes/s)\n",
2044 attr
->standard
.max_bw
);
2045 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2047 "Maximum Reservable Bandwidth: %g (Bytes/s)\n",
2048 attr
->standard
.max_rsv_bw
);
2049 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2050 sbuf_push(&sbuf
, 4, "Unreserved Bandwidth per Class Type\n");
2051 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
+= 2)
2053 "[%d]: %g (Bytes/sec)\t[%d]: %g (Bytes/s)\n",
2054 i
, attr
->standard
.unrsv_bw
[i
], i
+ 1,
2055 attr
->standard
.unrsv_bw
[i
+ 1]);
2057 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2058 sbuf_push(&sbuf
, 4, "Remote AS: %u\n",
2059 attr
->standard
.remote_as
);
2060 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
2061 sbuf_push(&sbuf
, 4, "Remote ASBR IPv4 address: %pI4\n",
2062 &attr
->standard
.remote_addr
);
2063 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
2064 sbuf_push(&sbuf
, 4, "Remote ASBR IPv6 address: %pI6\n",
2065 &attr
->standard
.remote_addr6
);
2066 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2067 sbuf_push(&sbuf
, 4, "Average Link Delay: %d (micro-sec)\n",
2068 attr
->extended
.delay
);
2069 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
))
2070 sbuf_push(&sbuf
, 4, "Min/Max Link Delay: %d/%d (micro-sec)\n",
2071 attr
->extended
.min_delay
, attr
->extended
.max_delay
);
2072 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2073 sbuf_push(&sbuf
, 4, "Delay Variation: %d (micro-sec)\n",
2074 attr
->extended
.jitter
);
2075 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2076 sbuf_push(&sbuf
, 4, "Link Loss: %g (%%)\n",
2077 (float)(attr
->extended
.pkt_loss
* LOSS_PRECISION
));
2078 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2079 sbuf_push(&sbuf
, 4, "Available Bandwidth: %g (Bytes/s)\n",
2080 attr
->extended
.ava_bw
);
2081 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2082 sbuf_push(&sbuf
, 4, "Residual Bandwidth: %g (Bytes/s)\n",
2083 attr
->extended
.rsv_bw
);
2084 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2085 sbuf_push(&sbuf
, 4, "Utilized Bandwidth: %g (Bytes/s)\n",
2086 attr
->extended
.used_bw
);
2087 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2088 sbuf_push(&sbuf
, 4, "Adjacency-SID: %u", attr
->adj_sid
[0].sid
);
2089 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2090 attr
->adj_sid
[0].flags
, attr
->adj_sid
[0].weight
);
2092 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2093 sbuf_push(&sbuf
, 4, "Bck. Adjacency-SID: %u",
2094 attr
->adj_sid
[1].sid
);
2095 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2096 attr
->adj_sid
[1].flags
, attr
->adj_sid
[1].weight
);
2098 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2099 sbuf_push(&sbuf
, 4, "SRLGs: %d", attr
->srlg_len
);
2100 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2102 sbuf_push(&sbuf
, 8, "\n%u", attr
->srlgs
[i
]);
2104 sbuf_push(&sbuf
, 8, ", %u", attr
->srlgs
[i
]);
2106 sbuf_push(&sbuf
, 0, "\n");
2110 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2114 static void ls_show_edge_json(struct ls_edge
*edge
, struct json_object
*json
)
2116 struct ls_attributes
*attr
;
2117 struct json_object
*jte
, *jbw
, *jobj
, *jsr
= NULL
, *jsrlg
;
2118 char buf
[INET6_BUFSIZ
];
2120 attr
= edge
->attributes
;
2122 json_object_int_add(json
, "edge-id", edge
->key
);
2123 json_object_string_add(json
, "status", status2txt
[edge
->status
]);
2124 json_object_string_add(json
, "origin", origin2txt
[attr
->adv
.origin
]);
2125 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
2126 json_object_string_add(json
, "advertised-router", buf
);
2128 json_object_int_add(json
, "local-vertex-id", edge
->source
->key
);
2129 if (edge
->destination
)
2130 json_object_int_add(json
, "remote-vertex-id",
2131 edge
->destination
->key
);
2132 json_object_int_add(json
, "metric", attr
->metric
);
2133 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2134 json_object_string_add(json
, "name", attr
->name
);
2135 jte
= json_object_new_object();
2136 json_object_object_add(json
, "edge-attributes", jte
);
2137 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2138 json_object_int_add(jte
, "te-metric", attr
->standard
.te_metric
);
2139 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2140 json_object_int_add(jte
, "admin-group",
2141 attr
->standard
.admin_group
);
2142 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)) {
2143 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.local
);
2144 json_object_string_add(jte
, "local-address", buf
);
2146 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
)) {
2147 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.remote
);
2148 json_object_string_add(jte
, "remote-address", buf
);
2150 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)) {
2151 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.local6
);
2152 json_object_string_add(jte
, "local-address-v6", buf
);
2154 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
)) {
2155 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.remote6
);
2156 json_object_string_add(jte
, "remote-address-v6", buf
);
2158 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2159 json_object_int_add(jte
, "local-identifier",
2160 attr
->standard
.local_id
);
2161 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2162 json_object_int_add(jte
, "remote-identifier",
2163 attr
->standard
.remote_id
);
2164 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2165 json_object_double_add(jte
, "max-link-bandwidth",
2166 attr
->standard
.max_bw
);
2167 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2168 json_object_double_add(jte
, "max-resv-link-bandwidth",
2169 attr
->standard
.max_rsv_bw
);
2170 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2171 jbw
= json_object_new_array();
2172 json_object_object_add(jte
, "unreserved-bandwidth", jbw
);
2173 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
++) {
2174 jobj
= json_object_new_object();
2175 snprintfrr(buf
, 13, "class-type-%u", i
);
2176 json_object_double_add(jobj
, buf
,
2177 attr
->standard
.unrsv_bw
[i
]);
2178 json_object_array_add(jbw
, jobj
);
2181 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2182 json_object_int_add(jte
, "remote-asn",
2183 attr
->standard
.remote_as
);
2184 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
)) {
2185 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4",
2186 &attr
->standard
.remote_addr
);
2187 json_object_string_add(jte
, "remote-as-address", buf
);
2189 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
)) {
2190 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6",
2191 &attr
->standard
.remote_addr6
);
2192 json_object_string_add(jte
, "remote-as-address-v6", buf
);
2194 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2195 json_object_int_add(jte
, "delay", attr
->extended
.delay
);
2196 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
2197 json_object_int_add(jte
, "min-delay", attr
->extended
.min_delay
);
2198 json_object_int_add(jte
, "max-delay", attr
->extended
.max_delay
);
2200 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2201 json_object_int_add(jte
, "jitter", attr
->extended
.jitter
);
2202 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2203 json_object_double_add(
2204 jte
, "loss", attr
->extended
.pkt_loss
* LOSS_PRECISION
);
2205 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2206 json_object_double_add(jte
, "available-bandwidth",
2207 attr
->extended
.ava_bw
);
2208 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2209 json_object_double_add(jte
, "residual-bandwidth",
2210 attr
->extended
.rsv_bw
);
2211 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2212 json_object_double_add(jte
, "utilized-bandwidth",
2213 attr
->extended
.used_bw
);
2214 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2215 jsrlg
= json_object_new_array();
2216 json_object_object_add(jte
, "srlgs", jsrlg
);
2217 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2218 jobj
= json_object_new_object();
2219 json_object_int_add(jobj
, "srlg", attr
->srlgs
[i
]);
2220 json_object_array_add(jsrlg
, jobj
);
2223 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2224 jsr
= json_object_new_array();
2225 json_object_object_add(json
, "segment-routing", jsr
);
2226 jobj
= json_object_new_object();
2227 json_object_int_add(jobj
, "adj-sid", attr
->adj_sid
[0].sid
);
2228 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[0].flags
);
2229 json_object_string_add(jobj
, "flags", buf
);
2230 json_object_int_add(jobj
, "weight", attr
->adj_sid
[0].weight
);
2231 json_object_array_add(jsr
, jobj
);
2233 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2235 jsr
= json_object_new_array();
2236 json_object_object_add(json
, "segment-routing", jsr
);
2238 jobj
= json_object_new_object();
2239 json_object_int_add(jobj
, "adj-sid", attr
->adj_sid
[1].sid
);
2240 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[1].flags
);
2241 json_object_string_add(jobj
, "flags", buf
);
2242 json_object_int_add(jobj
, "weight", attr
->adj_sid
[1].weight
);
2243 json_object_array_add(jsr
, jobj
);
2247 void ls_show_edge(struct ls_edge
*edge
, struct vty
*vty
,
2248 struct json_object
*json
, bool verbose
)
2255 ls_show_edge_json(edge
, json
);
2257 ls_show_edge_vty(edge
, vty
, verbose
);
2260 void ls_show_edges(struct ls_ted
*ted
, struct vty
*vty
,
2261 struct json_object
*json
, bool verbose
)
2263 struct ls_edge
*edge
;
2264 json_object
*jedges
, *jedge
;
2267 jedges
= json_object_new_array();
2268 json_object_object_add(json
, "edges", jedges
);
2269 frr_each (edges
, &ted
->edges
, edge
) {
2270 jedge
= json_object_new_object();
2271 ls_show_edge(edge
, NULL
, jedge
, verbose
);
2272 json_object_array_add(jedges
, jedge
);
2275 frr_each (edges
, &ted
->edges
, edge
)
2276 ls_show_edge(edge
, vty
, NULL
, verbose
);
2280 static void ls_show_subnet_vty(struct ls_subnet
*subnet
, struct vty
*vty
,
2283 struct ls_prefix
*pref
;
2285 char buf
[INET6_BUFSIZ
];
2287 pref
= subnet
->ls_pref
;
2288 sbuf_init(&sbuf
, NULL
, 0);
2290 sbuf_push(&sbuf
, 2, "Subnet: %pFX", &subnet
->key
);
2291 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2292 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
2293 sbuf_push(&sbuf
, 0, "\tMetric: %d", pref
->metric
);
2294 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[subnet
->status
]);
2299 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[pref
->adv
.origin
]);
2300 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
))
2301 sbuf_push(&sbuf
, 4, "Flags: %d\n", pref
->igp_flag
);
2303 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2304 sbuf_push(&sbuf
, 4, "Tag: %d\n", pref
->route_tag
);
2306 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2307 sbuf_push(&sbuf
, 4, "Extended Tag: %" PRIu64
"\n",
2308 pref
->extended_tag
);
2310 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
))
2311 sbuf_push(&sbuf
, 4, "SID: %d\tAlgorithm: %d\tFlags: 0x%x\n",
2312 pref
->sr
.sid
, pref
->sr
.algo
, pref
->sr
.sid_flag
);
2315 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2319 static void ls_show_subnet_json(struct ls_subnet
*subnet
,
2320 struct json_object
*json
)
2322 struct ls_prefix
*pref
;
2324 char buf
[INET6_BUFSIZ
];
2326 pref
= subnet
->ls_pref
;
2328 snprintfrr(buf
, INET6_BUFSIZ
, "%pFX", &subnet
->key
);
2329 json_object_string_add(json
, "subnet-id", buf
);
2330 json_object_string_add(json
, "status", status2txt
[subnet
->status
]);
2331 json_object_string_add(json
, "origin", origin2txt
[pref
->adv
.origin
]);
2332 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2333 json_object_string_add(json
, "advertised-router", buf
);
2335 json_object_int_add(json
, "vertex-id", subnet
->vertex
->key
);
2336 json_object_int_add(json
, "metric", pref
->metric
);
2337 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
)) {
2338 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->igp_flag
);
2339 json_object_string_add(json
, "flags", buf
);
2341 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2342 json_object_int_add(json
, "tag", pref
->route_tag
);
2343 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2344 json_object_int_add(json
, "extended-tag", pref
->extended_tag
);
2345 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
)) {
2346 jsr
= json_object_new_object();
2347 json_object_object_add(json
, "segment-routing", jsr
);
2348 json_object_int_add(jsr
, "pref-sid", pref
->sr
.sid
);
2349 json_object_int_add(jsr
, "algo", pref
->sr
.algo
);
2350 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->sr
.sid_flag
);
2351 json_object_string_add(jsr
, "flags", buf
);
2355 void ls_show_subnet(struct ls_subnet
*subnet
, struct vty
*vty
,
2356 struct json_object
*json
, bool verbose
)
2363 ls_show_subnet_json(subnet
, json
);
2365 ls_show_subnet_vty(subnet
, vty
, verbose
);
2368 void ls_show_subnets(struct ls_ted
*ted
, struct vty
*vty
,
2369 struct json_object
*json
, bool verbose
)
2371 struct ls_subnet
*subnet
;
2372 json_object
*jsubs
, *jsub
;
2375 jsubs
= json_object_new_array();
2376 json_object_object_add(json
, "subnets", jsubs
);
2377 frr_each (subnets
, &ted
->subnets
, subnet
) {
2378 jsub
= json_object_new_object();
2379 ls_show_subnet(subnet
, NULL
, jsub
, verbose
);
2380 json_object_array_add(jsubs
, jsub
);
2383 frr_each (subnets
, &ted
->subnets
, subnet
)
2384 ls_show_subnet(subnet
, vty
, NULL
, verbose
);
2388 void ls_show_ted(struct ls_ted
*ted
, struct vty
*vty
, struct json_object
*json
,
2394 jted
= json_object_new_object();
2395 json_object_object_add(json
, "ted", jted
);
2396 json_object_string_add(jted
, "name", ted
->name
);
2397 json_object_int_add(jted
, "key", ted
->key
);
2398 json_object_int_add(jted
, "verticesCount",
2399 vertices_count(&ted
->vertices
));
2400 json_object_int_add(jted
, "edgesCount",
2401 edges_count(&ted
->edges
));
2402 json_object_int_add(jted
, "subnetsCount",
2403 subnets_count(&ted
->subnets
));
2404 ls_show_vertices(ted
, NULL
, jted
, verbose
);
2405 ls_show_edges(ted
, NULL
, jted
, verbose
);
2406 ls_show_subnets(ted
, NULL
, jted
, verbose
);
2412 "\n\tTraffic Engineering Database: %s (key: %d)\n\n",
2413 ted
->name
, ted
->key
);
2414 ls_show_vertices(ted
, vty
, NULL
, verbose
);
2415 ls_show_edges(ted
, vty
, NULL
, verbose
);
2416 ls_show_subnets(ted
, vty
, NULL
, verbose
);
2418 "\n\tTotal: %zu Vertices, %zu Edges, %zu Subnets\n\n",
2419 vertices_count(&ted
->vertices
),
2420 edges_count(&ted
->edges
), subnets_count(&ted
->subnets
));
2424 void ls_dump_ted(struct ls_ted
*ted
)
2426 struct ls_vertex
*vertex
;
2427 struct ls_edge
*edge
;
2428 struct ls_subnet
*subnet
;
2429 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
2431 zlog_debug("(%s) Ted init", __func__
);
2433 /* Loop TED, start printing Node, then Attributes and finally Prefix */
2434 frr_each (vertices
, &ted
->vertices
, vertex
) {
2435 zlog_debug(" Ted node (%s %pI4 %s)",
2436 vertex
->node
->name
[0] ? vertex
->node
->name
2438 &vertex
->node
->router_id
,
2439 origin2txt
[vertex
->node
->adv
.origin
]);
2440 struct listnode
*lst_node
;
2441 struct ls_edge
*vertex_edge
;
2443 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, lst_node
,
2446 " inc edge key:%" PRIu64
" attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2448 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2449 &vertex_edge
->attributes
->standard
.local
,
2450 &vertex_edge
->attributes
->standard
.remote
);
2452 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, lst_node
,
2455 " out edge key:%" PRIu64
" attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2457 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2458 &vertex_edge
->attributes
->standard
.local
,
2459 &vertex_edge
->attributes
->standard
.remote
);
2462 frr_each (edges
, &ted
->edges
, edge
) {
2463 zlog_debug(" Ted edge key:%" PRIu64
"src:%pI4 dst:%pI4", edge
->key
,
2464 edge
->source
? &edge
->source
->node
->router_id
2467 ? &edge
->destination
->node
->router_id
2470 frr_each (subnets
, &ted
->subnets
, subnet
) {
2471 zlog_debug(" Ted subnet key:%pFX vertex:%pI4",
2472 &subnet
->ls_pref
->pref
,
2473 &subnet
->vertex
->node
->adv
.id
.ip
.addr
);
2475 zlog_debug("(%s) Ted end", __func__
);