]>
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
);
84 int ls_node_same(struct ls_node
*n1
, struct ls_node
*n2
)
86 if ((n1
&& !n2
) || (!n1
&& n2
))
92 if (n1
->flags
!= n2
->flags
)
95 if (n1
->adv
.origin
!= n2
->adv
.origin
)
98 if (!memcmp(&n1
->adv
.id
, &n2
->adv
.id
, sizeof(struct ls_node_id
)))
101 /* Do we need to test individually each field, instead performing a
102 * global memcmp? There is a risk that an old value that is bit masked
103 * i.e. corresponding flag = 0, will result into a false negative
105 if (!memcmp(n1
, n2
, sizeof(struct ls_node
)))
112 * Link State Attributes management functions
114 struct ls_attributes
*ls_attributes_new(struct ls_node_id adv
,
115 struct in_addr local
,
116 struct in6_addr local6
,
119 struct ls_attributes
*new;
121 if (adv
.origin
== UNKNOWN
)
124 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
126 if (!IPV4_NET0(local
.s_addr
)) {
127 new->standard
.local
= local
;
128 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
);
130 if (!IN6_IS_ADDR_UNSPECIFIED(&local6
)) {
131 new->standard
.local6
= local6
;
132 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR6
);
135 new->standard
.local_id
= local_id
;
136 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ID
);
139 /* Check that almost one identifier is set */
140 if (!CHECK_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
| LS_ATTR_LOCAL_ADDR6
141 | LS_ATTR_LOCAL_ID
)) {
142 XFREE(MTYPE_LS_DB
, new);
149 void ls_attributes_srlg_del(struct ls_attributes
*attr
)
155 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
159 UNSET_FLAG(attr
->flags
, LS_ATTR_SRLG
);
162 void ls_attributes_del(struct ls_attributes
*attr
)
167 ls_attributes_srlg_del(attr
);
169 XFREE(MTYPE_LS_DB
, attr
);
172 int ls_attributes_same(struct ls_attributes
*l1
, struct ls_attributes
*l2
)
174 if ((l1
&& !l2
) || (!l1
&& l2
))
180 if (l1
->flags
!= l2
->flags
)
183 if (l1
->adv
.origin
!= l2
->adv
.origin
)
186 if (!memcmp(&l1
->adv
.id
, &l2
->adv
.id
, sizeof(struct ls_node_id
)))
189 /* Do we need to test individually each field, instead performing a
190 * global memcmp? There is a risk that an old value that is bit masked
191 * i.e. corresponding flag = 0, will result into a false negative
193 if (!memcmp(l1
, l2
, sizeof(struct ls_attributes
)))
200 * Link State prefix management functions
202 struct ls_prefix
*ls_prefix_new(struct ls_node_id adv
, struct prefix p
)
204 struct ls_prefix
*new;
206 if (adv
.origin
== UNKNOWN
)
209 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
216 void ls_prefix_del(struct ls_prefix
*pref
)
221 XFREE(MTYPE_LS_DB
, pref
);
224 int ls_prefix_same(struct ls_prefix
*p1
, struct ls_prefix
*p2
)
226 if ((p1
&& !p2
) || (!p1
&& p2
))
232 if (p1
->flags
!= p2
->flags
)
235 if (p1
->adv
.origin
!= p2
->adv
.origin
)
238 if (!memcmp(&p1
->adv
.id
, &p2
->adv
.id
, sizeof(struct ls_node_id
)))
241 /* Do we need to test individually each field, instead performing a
242 * global memcmp? There is a risk that an old value that is bit masked
243 * i.e. corresponding flag = 0, will result into a false negative
245 if (!memcmp(p1
, p2
, sizeof(struct ls_prefix
)))
252 * Link State Vertices management functions
254 struct ls_vertex
*ls_vertex_add(struct ls_ted
*ted
, struct ls_node
*node
)
256 struct ls_vertex
*new;
259 if ((ted
== NULL
) || (node
== NULL
))
262 /* set Key as the IPv4/Ipv6 Router ID or ISO System ID */
263 switch (node
->adv
.origin
) {
267 key
= ((uint64_t)ntohl(node
->adv
.id
.ip
.addr
.s_addr
))
272 memcpy(&key
, &node
->adv
.id
.iso
.sys_id
, ISO_SYS_ID_LEN
);
279 /* Check that key is valid */
283 /* Create Vertex and add it to the TED */
284 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_vertex
));
292 new->incoming_edges
= list_new();
293 new->incoming_edges
->cmp
= (int (*)(void *, void *))edge_cmp
;
294 new->outgoing_edges
= list_new();
295 new->outgoing_edges
->cmp
= (int (*)(void *, void *))edge_cmp
;
296 new->prefixes
= list_new();
297 new->prefixes
->cmp
= (int (*)(void *, void *))subnet_cmp
;
298 vertices_add(&ted
->vertices
, new);
303 void ls_vertex_del(struct ls_ted
*ted
, struct ls_vertex
*vertex
)
305 struct listnode
*node
, *nnode
;
306 struct ls_edge
*edge
;
307 struct ls_subnet
*subnet
;
312 /* Remove outgoing Edges and list */
313 for (ALL_LIST_ELEMENTS(vertex
->outgoing_edges
, node
, nnode
, edge
))
314 ls_edge_del_all(ted
, edge
);
315 list_delete(&vertex
->outgoing_edges
);
317 /* Disconnect incoming Edges and remove list */
318 for (ALL_LIST_ELEMENTS(vertex
->incoming_edges
, node
, nnode
, edge
)) {
319 ls_disconnect(vertex
, edge
, false);
320 if (edge
->source
== NULL
)
321 ls_edge_del_all(ted
, edge
);
323 list_delete(&vertex
->incoming_edges
);
325 /* Remove subnet and list */
326 for (ALL_LIST_ELEMENTS(vertex
->prefixes
, node
, nnode
, subnet
))
327 ls_subnet_del_all(ted
, subnet
);
328 list_delete(&vertex
->prefixes
);
330 /* Then remove Vertex from Link State Data Base and free memory */
331 vertices_del(&ted
->vertices
, vertex
);
332 XFREE(MTYPE_LS_DB
, vertex
);
336 void ls_vertex_del_all(struct ls_ted
*ted
, struct ls_vertex
*vertex
)
341 /* First remove associated Link State Node */
342 ls_node_del(vertex
->node
);
344 /* Then, Vertex itself */
345 ls_vertex_del(ted
, vertex
);
348 struct ls_vertex
*ls_vertex_update(struct ls_ted
*ted
, struct ls_node
*node
)
350 struct ls_vertex
*old
;
355 old
= ls_find_vertex_by_id(ted
, node
->adv
);
357 if (!ls_node_same(old
->node
, node
)) {
358 ls_node_del(old
->node
);
361 old
->status
= UPDATE
;
365 return ls_vertex_add(ted
, node
);
368 struct ls_vertex
*ls_find_vertex_by_key(struct ls_ted
*ted
, const uint64_t key
)
370 struct ls_vertex vertex
= {};
376 return vertices_find(&ted
->vertices
, &vertex
);
379 struct ls_vertex
*ls_find_vertex_by_id(struct ls_ted
*ted
,
380 struct ls_node_id nid
)
382 struct ls_vertex vertex
= {};
385 switch (nid
.origin
) {
390 ((uint64_t)ntohl(nid
.id
.ip
.addr
.s_addr
)) & 0xffffffff;
394 memcpy(&vertex
.key
, &nid
.id
.iso
.sys_id
, ISO_SYS_ID_LEN
);
400 return vertices_find(&ted
->vertices
, &vertex
);
403 int ls_vertex_same(struct ls_vertex
*v1
, struct ls_vertex
*v2
)
405 if ((v1
&& !v2
) || (!v1
&& v2
))
411 if (v1
->key
!= v2
->key
)
414 if (v1
->node
== v2
->node
)
417 return ls_node_same(v1
->node
, v2
->node
);
420 void ls_vertex_clean(struct ls_ted
*ted
, struct ls_vertex
*vertex
,
421 struct zclient
*zclient
)
423 struct listnode
*node
, *nnode
;
424 struct ls_edge
*edge
;
425 struct ls_subnet
*subnet
;
426 struct ls_message msg
;
428 /* Remove Orphan Edge ... */
429 for (ALL_LIST_ELEMENTS(vertex
->outgoing_edges
, node
, nnode
, edge
)) {
430 if (edge
->status
== ORPHAN
) {
432 edge
->status
= DELETE
;
433 ls_edge2msg(&msg
, edge
);
434 ls_send_msg(zclient
, &msg
, NULL
);
436 ls_edge_del_all(ted
, edge
);
439 for (ALL_LIST_ELEMENTS(vertex
->incoming_edges
, node
, nnode
, edge
)) {
440 if (edge
->status
== ORPHAN
) {
442 edge
->status
= DELETE
;
443 ls_edge2msg(&msg
, edge
);
444 ls_send_msg(zclient
, &msg
, NULL
);
446 ls_edge_del_all(ted
, edge
);
450 /* ... and Subnet from the Vertex */
451 for (ALL_LIST_ELEMENTS(vertex
->prefixes
, node
, nnode
, subnet
)) {
452 if (subnet
->status
== ORPHAN
) {
454 subnet
->status
= DELETE
;
455 ls_subnet2msg(&msg
, subnet
);
456 ls_send_msg(zclient
, &msg
, NULL
);
458 ls_subnet_del_all(ted
, subnet
);
464 * Link State Edges management functions
468 * This function allows to connect the Edge to the vertices present in the TED.
469 * A temporary vertex that corresponds to the source of this Edge i.e. the
470 * advertised router, is created if not found in the Data Base. If a Edge that
471 * corresponds to the reverse path is found, the Edge is attached to the
472 * destination vertex as destination and reverse Edge is attached to the source
475 * @param ted Link State Data Base
476 * @param edge Link State Edge to be attached
478 static void ls_edge_connect_to(struct ls_ted
*ted
, struct ls_edge
*edge
)
480 struct ls_vertex
*vertex
= NULL
;
481 struct ls_node
*node
;
483 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
485 /* First, search if there is a Vertex that correspond to the Node ID */
486 vertex
= ls_find_vertex_by_id(ted
, edge
->attributes
->adv
);
487 if (vertex
== NULL
) {
488 /* Create a new temporary Node & Vertex if not found */
489 node
= ls_node_new(edge
->attributes
->adv
, inaddr_any
,
491 vertex
= ls_vertex_add(ted
, node
);
493 /* and attach the edge as source to the vertex */
494 listnode_add_sort_nodup(vertex
->outgoing_edges
, edge
);
495 edge
->source
= vertex
;
497 /* Then search if there is a reverse Edge */
498 dst
= ls_find_edge_by_destination(ted
, edge
->attributes
);
499 /* attach the destination edge to the vertex */
501 listnode_add_sort_nodup(vertex
->incoming_edges
, dst
);
502 dst
->destination
= vertex
;
503 /* and destination vertex to this edge */
504 vertex
= dst
->source
;
505 listnode_add_sort_nodup(vertex
->incoming_edges
, edge
);
506 edge
->destination
= vertex
;
510 struct ls_edge
*ls_edge_add(struct ls_ted
*ted
,
511 struct ls_attributes
*attributes
)
516 if (attributes
== NULL
)
519 /* Key is the IPv4 local address */
520 if (!IPV4_NET0(attributes
->standard
.local
.s_addr
))
521 key
= ((uint64_t)ntohl(attributes
->standard
.local
.s_addr
))
523 /* or the IPv6 local address if IPv4 is not defined */
524 else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes
->standard
.local6
))
525 key
= (uint64_t)(attributes
->standard
.local6
.s6_addr32
[0]
527 | ((uint64_t)attributes
->standard
.local6
.s6_addr32
[1]
529 /* of local identifier if no IP addresses are defined */
530 else if (attributes
->standard
.local_id
!= 0)
532 (attributes
->standard
.local_id
& 0xffffffff)
533 | ((uint64_t)attributes
->standard
.remote_id
<< 32));
535 /* Check that key is valid */
539 /* Create Edge and add it to the TED */
540 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_edge
));
542 new->attributes
= attributes
;
546 edges_add(&ted
->edges
, new);
548 /* Finally, connect Edge to Vertices */
549 ls_edge_connect_to(ted
, new);
554 struct ls_edge
*ls_find_edge_by_key(struct ls_ted
*ted
, const uint64_t key
)
556 struct ls_edge edge
= {};
562 return edges_find(&ted
->edges
, &edge
);
565 struct ls_edge
*ls_find_edge_by_source(struct ls_ted
*ted
,
566 struct ls_attributes
*attributes
)
568 struct ls_edge edge
= {};
570 if (attributes
== NULL
)
574 /* Key is the IPv4 local address */
575 if (!IPV4_NET0(attributes
->standard
.local
.s_addr
))
576 edge
.key
= ((uint64_t)ntohl(attributes
->standard
.local
.s_addr
))
578 /* or the IPv6 local address if IPv4 is not defined */
579 else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes
->standard
.local6
))
580 edge
.key
= (uint64_t)(attributes
->standard
.local6
.s6_addr32
[0]
582 | ((uint64_t)attributes
->standard
.local6
.s6_addr32
[1]
584 /* of local identifier if no IP addresses are defined */
585 else if (attributes
->standard
.local_id
!= 0)
586 edge
.key
= (uint64_t)(
587 (attributes
->standard
.local_id
& 0xffffffff)
588 | ((uint64_t)attributes
->standard
.remote_id
<< 32));
593 return edges_find(&ted
->edges
, &edge
);
596 struct ls_edge
*ls_find_edge_by_destination(struct ls_ted
*ted
,
597 struct ls_attributes
*attributes
)
599 struct ls_edge edge
= {};
601 if (attributes
== NULL
)
605 /* Key is the IPv4 remote address */
606 if (!IPV4_NET0(attributes
->standard
.remote
.s_addr
))
607 edge
.key
= ((uint64_t)ntohl(attributes
->standard
.remote
.s_addr
))
609 /* or the IPv6 remote address if IPv4 is not defined */
610 else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes
->standard
.remote6
))
612 (uint64_t)(attributes
->standard
.remote6
.s6_addr32
[0]
614 | ((uint64_t)attributes
->standard
.remote6
.s6_addr32
[1]
616 /* of remote identifier if no IP addresses are defined */
617 else if (attributes
->standard
.remote_id
!= 0)
618 edge
.key
= (uint64_t)(
619 (attributes
->standard
.remote_id
& 0xffffffff)
620 | ((uint64_t)attributes
->standard
.local_id
<< 32));
625 return edges_find(&ted
->edges
, &edge
);
628 struct ls_edge
*ls_edge_update(struct ls_ted
*ted
,
629 struct ls_attributes
*attributes
)
633 if (attributes
== NULL
)
636 /* First, search for an existing Edge */
637 old
= ls_find_edge_by_source(ted
, attributes
);
639 /* Check if attributes are similar */
640 if (!ls_attributes_same(old
->attributes
, attributes
)) {
641 ls_attributes_del(old
->attributes
);
642 old
->attributes
= attributes
;
644 old
->status
= UPDATE
;
648 /* If not found, add new Edge from the attributes */
649 return ls_edge_add(ted
, attributes
);
652 int ls_edge_same(struct ls_edge
*e1
, struct ls_edge
*e2
)
654 if ((e1
&& !e2
) || (!e1
&& e2
))
660 if (e1
->key
!= e2
->key
)
663 if (e1
->attributes
== e2
->attributes
)
666 return ls_attributes_same(e1
->attributes
, e2
->attributes
);
669 void ls_edge_del(struct ls_ted
*ted
, struct ls_edge
*edge
)
674 /* Fist disconnect Edge from Vertices */
675 ls_disconnect_edge(edge
);
676 /* Then remove it from the Data Base */
677 edges_del(&ted
->edges
, edge
);
678 XFREE(MTYPE_LS_DB
, edge
);
681 void ls_edge_del_all(struct ls_ted
*ted
, struct ls_edge
*edge
)
686 /* Remove associated Link State Attributes */
687 ls_attributes_del(edge
->attributes
);
688 /* Then Edge itself */
689 ls_edge_del(ted
, edge
);
693 * Link State Subnet Management functions.
695 struct ls_subnet
*ls_subnet_add(struct ls_ted
*ted
,
696 struct ls_prefix
*ls_pref
)
698 struct ls_subnet
*new;
699 struct ls_vertex
*vertex
;
700 struct ls_node
*node
;
701 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
706 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_subnet
));
707 new->ls_pref
= ls_pref
;
708 new->key
= ls_pref
->pref
;
713 vertex
= ls_find_vertex_by_id(ted
, ls_pref
->adv
);
714 if (vertex
== NULL
) {
715 /* Create a new temporary Node & Vertex if not found */
716 node
= ls_node_new(ls_pref
->adv
, inaddr_any
, in6addr_any
);
717 vertex
= ls_vertex_add(ted
, node
);
719 /* And attach the subnet to the corresponding Vertex */
720 new->vertex
= vertex
;
721 listnode_add_sort_nodup(vertex
->prefixes
, new);
723 subnets_add(&ted
->subnets
, new);
728 struct ls_subnet
*ls_subnet_update(struct ls_ted
*ted
, struct ls_prefix
*pref
)
730 struct ls_subnet
*old
;
735 old
= ls_find_subnet(ted
, pref
->pref
);
737 if (!ls_prefix_same(old
->ls_pref
, pref
)) {
738 ls_prefix_del(old
->ls_pref
);
741 old
->status
= UPDATE
;
745 return ls_subnet_add(ted
, pref
);
748 int ls_subnet_same(struct ls_subnet
*s1
, struct ls_subnet
*s2
)
750 if ((s1
&& !s2
) || (!s1
&& s2
))
756 if (!prefix_same(&s1
->key
, &s2
->key
))
759 if (s1
->ls_pref
== s2
->ls_pref
)
762 return ls_prefix_same(s1
->ls_pref
, s2
->ls_pref
);
765 void ls_subnet_del(struct ls_ted
*ted
, struct ls_subnet
*subnet
)
770 /* First, disconnect Subnet from associated Vertex */
771 listnode_delete(subnet
->vertex
->prefixes
, subnet
);
772 /* Then delete Subnet */
773 subnets_del(&ted
->subnets
, subnet
);
774 XFREE(MTYPE_LS_DB
, subnet
);
777 void ls_subnet_del_all(struct ls_ted
*ted
, struct ls_subnet
*subnet
)
782 /* First, remove associated Link State Subnet */
783 ls_prefix_del(subnet
->ls_pref
);
784 /* Then, delete Subnet itself */
785 ls_subnet_del(ted
, subnet
);
788 struct ls_subnet
*ls_find_subnet(struct ls_ted
*ted
, const struct prefix prefix
)
790 struct ls_subnet subnet
= {};
793 return subnets_find(&ted
->subnets
, &subnet
);
797 * Link State TED management functions
799 struct ls_ted
*ls_ted_new(const uint32_t key
, const char *name
,
804 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_ted
));
806 /* Set basic information for this ted */
808 new->as_number
= as_number
;
809 strlcpy(new->name
, name
, MAX_NAME_LENGTH
);
811 /* Initialize the various RB tree */
812 vertices_init(&new->vertices
);
813 edges_init(&new->edges
);
814 subnets_init(&new->subnets
);
819 void ls_ted_del(struct ls_ted
*ted
)
824 /* Check that TED is empty */
825 if (vertices_count(&ted
->vertices
) || edges_count(&ted
->edges
)
826 || subnets_count(&ted
->subnets
))
829 /* Release RB Tree */
830 vertices_fini(&ted
->vertices
);
831 edges_fini(&ted
->edges
);
832 subnets_fini(&ted
->subnets
);
834 XFREE(MTYPE_LS_DB
, ted
);
837 void ls_ted_del_all(struct ls_ted
*ted
)
839 struct ls_vertex
*vertex
;
840 struct ls_edge
*edge
;
841 struct ls_subnet
*subnet
;
846 /* First remove Vertices, Edges and Subnets and associated Link State */
847 frr_each (vertices
, &ted
->vertices
, vertex
)
848 ls_vertex_del_all(ted
, vertex
);
849 frr_each (edges
, &ted
->edges
, edge
)
850 ls_edge_del_all(ted
, edge
);
851 frr_each (subnets
, &ted
->subnets
, subnet
)
852 ls_subnet_del_all(ted
, subnet
);
854 /* then remove TED itself */
858 void ls_ted_clean(struct ls_ted
*ted
)
860 struct ls_vertex
*vertex
;
861 struct ls_edge
*edge
;
862 struct ls_subnet
*subnet
;
867 /* First, start with Vertices */
868 frr_each (vertices
, &ted
->vertices
, vertex
)
869 if (vertex
->status
== ORPHAN
)
870 ls_vertex_del_all(ted
, vertex
);
873 frr_each (edges
, &ted
->edges
, edge
)
874 if (edge
->status
== ORPHAN
)
875 ls_edge_del_all(ted
, edge
);
878 frr_each (subnets
, &ted
->subnets
, subnet
)
879 if (subnet
->status
== ORPHAN
)
880 ls_subnet_del_all(ted
, subnet
);
884 void ls_connect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
886 if (vertex
== NULL
|| edge
== NULL
)
890 listnode_add_sort_nodup(vertex
->outgoing_edges
, edge
);
891 edge
->source
= vertex
;
893 listnode_add_sort_nodup(vertex
->incoming_edges
, edge
);
894 edge
->destination
= vertex
;
898 void ls_disconnect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
901 if (vertex
== NULL
|| edge
== NULL
)
905 listnode_delete(vertex
->outgoing_edges
, edge
);
908 listnode_delete(vertex
->incoming_edges
, edge
);
909 edge
->destination
= NULL
;
913 void ls_connect_vertices(struct ls_vertex
*src
, struct ls_vertex
*dst
,
914 struct ls_edge
*edge
)
920 edge
->destination
= dst
;
923 listnode_add_sort_nodup(src
->outgoing_edges
, edge
);
926 listnode_add_sort_nodup(dst
->incoming_edges
, edge
);
929 void ls_disconnect_edge(struct ls_edge
*edge
)
934 ls_disconnect(edge
->source
, edge
, true);
935 ls_disconnect(edge
->destination
, edge
, false);
937 /* Mark this Edge as ORPHAN for future cleanup */
938 edge
->status
= ORPHAN
;
942 * Link State Message management functions
945 int ls_register(struct zclient
*zclient
, bool server
)
950 rc
= zclient_register_opaque(zclient
, LINK_STATE_SYNC
);
952 rc
= zclient_register_opaque(zclient
, LINK_STATE_UPDATE
);
957 int ls_unregister(struct zclient
*zclient
, bool server
)
962 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_SYNC
);
964 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_UPDATE
);
969 int ls_request_sync(struct zclient
*zclient
)
974 /* Check buffer size */
975 if (STREAM_SIZE(zclient
->obuf
)
976 < (ZEBRA_HEADER_SIZE
+ 3 * sizeof(uint32_t)))
982 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
984 /* Set type and flags */
985 stream_putl(s
, LINK_STATE_SYNC
);
986 stream_putw(s
, flags
);
987 /* Send destination client info */
988 stream_putc(s
, zclient
->redist_default
);
989 stream_putw(s
, zclient
->instance
);
990 stream_putl(s
, zclient
->session_id
);
992 /* Put length into the header at the start of the stream. */
993 stream_putw_at(s
, 0, stream_get_endp(s
));
995 return zclient_send_message(zclient
);
998 static struct ls_node
*ls_parse_node(struct stream
*s
)
1000 struct ls_node
*node
;
1003 node
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
1005 STREAM_GET(&node
->adv
, s
, sizeof(struct ls_node_id
));
1006 STREAM_GETW(s
, node
->flags
);
1007 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1008 STREAM_GETC(s
, len
);
1009 STREAM_GET(node
->name
, s
, len
);
1011 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1012 node
->router_id
.s_addr
= stream_get_ipv4(s
);
1013 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1014 STREAM_GET(&node
->router6_id
, s
, IPV6_MAX_BYTELEN
);
1015 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1016 STREAM_GETC(s
, node
->node_flag
);
1017 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1018 STREAM_GETC(s
, node
->type
);
1019 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1020 STREAM_GETL(s
, node
->as_number
);
1021 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1022 STREAM_GETL(s
, node
->srgb
.lower_bound
);
1023 STREAM_GETL(s
, node
->srgb
.range_size
);
1024 STREAM_GETC(s
, node
->srgb
.flag
);
1025 STREAM_GET(node
->algo
, s
, 2);
1027 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1028 STREAM_GETL(s
, node
->srlb
.lower_bound
);
1029 STREAM_GETL(s
, node
->srlb
.range_size
);
1031 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1032 STREAM_GETC(s
, node
->msd
);
1037 zlog_err("LS(%s): Could not parse Link State Node. Abort!", __func__
);
1038 XFREE(MTYPE_LS_DB
, node
);
1042 static struct ls_attributes
*ls_parse_attributes(struct stream
*s
)
1044 struct ls_attributes
*attr
;
1047 attr
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
1050 STREAM_GET(&attr
->adv
, s
, sizeof(struct ls_node_id
));
1051 STREAM_GETL(s
, attr
->flags
);
1052 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1053 STREAM_GETC(s
, len
);
1054 STREAM_GET(attr
->name
, s
, len
);
1056 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1057 STREAM_GETL(s
, attr
->metric
);
1058 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1059 STREAM_GETL(s
, attr
->standard
.te_metric
);
1060 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1061 STREAM_GETL(s
, attr
->standard
.admin_group
);
1062 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1063 attr
->standard
.local
.s_addr
= stream_get_ipv4(s
);
1064 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1065 attr
->standard
.remote
.s_addr
= stream_get_ipv4(s
);
1066 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1067 STREAM_GET(&attr
->standard
.local6
, s
, IPV6_MAX_BYTELEN
);
1068 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1069 STREAM_GET(&attr
->standard
.remote6
, s
, IPV6_MAX_BYTELEN
);
1070 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1071 STREAM_GETL(s
, attr
->standard
.local_id
);
1072 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1073 STREAM_GETL(s
, attr
->standard
.remote_id
);
1074 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1075 STREAM_GETF(s
, attr
->standard
.max_bw
);
1076 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1077 STREAM_GETF(s
, attr
->standard
.max_rsv_bw
);
1078 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1079 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1080 STREAM_GETF(s
, attr
->standard
.unrsv_bw
[len
]);
1081 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1082 STREAM_GETL(s
, attr
->standard
.remote_as
);
1083 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1084 attr
->standard
.remote_addr
.s_addr
= stream_get_ipv4(s
);
1085 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1086 STREAM_GET(&attr
->standard
.remote_addr6
, s
, IPV6_MAX_BYTELEN
);
1087 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1088 STREAM_GETL(s
, attr
->extended
.delay
);
1089 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1090 STREAM_GETL(s
, attr
->extended
.min_delay
);
1091 STREAM_GETL(s
, attr
->extended
.max_delay
);
1093 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1094 STREAM_GETL(s
, attr
->extended
.jitter
);
1095 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1096 STREAM_GETL(s
, attr
->extended
.pkt_loss
);
1097 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1098 STREAM_GETF(s
, attr
->extended
.ava_bw
);
1099 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1100 STREAM_GETF(s
, attr
->extended
.rsv_bw
);
1101 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1102 STREAM_GETF(s
, attr
->extended
.used_bw
);
1103 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1104 STREAM_GETL(s
, attr
->adj_sid
[0].sid
);
1105 STREAM_GETC(s
, attr
->adj_sid
[0].flags
);
1106 STREAM_GETC(s
, attr
->adj_sid
[0].weight
);
1107 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1108 STREAM_GET(attr
->adj_sid
[0].neighbor
.sysid
, s
,
1110 else if (attr
->adv
.origin
== OSPFv2
)
1111 attr
->adj_sid
[0].neighbor
.addr
.s_addr
=
1114 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1115 STREAM_GETL(s
, attr
->adj_sid
[1].sid
);
1116 STREAM_GETC(s
, attr
->adj_sid
[1].flags
);
1117 STREAM_GETC(s
, attr
->adj_sid
[1].weight
);
1118 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1119 STREAM_GET(attr
->adj_sid
[1].neighbor
.sysid
, s
,
1121 else if (attr
->adv
.origin
== OSPFv2
)
1122 attr
->adj_sid
[1].neighbor
.addr
.s_addr
=
1125 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1126 STREAM_GETC(s
, len
);
1127 attr
->srlgs
= XCALLOC(MTYPE_LS_DB
, len
*sizeof(uint32_t));
1128 attr
->srlg_len
= len
;
1129 for (len
= 0; len
< attr
->srlg_len
; len
++)
1130 STREAM_GETL(s
, attr
->srlgs
[len
]);
1136 zlog_err("LS(%s): Could not parse Link State Attributes. Abort!",
1138 /* Clean memory allocation */
1139 if (attr
->srlgs
!= NULL
)
1140 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
1141 XFREE(MTYPE_LS_DB
, attr
);
1146 static struct ls_prefix
*ls_parse_prefix(struct stream
*s
)
1148 struct ls_prefix
*ls_pref
;
1151 ls_pref
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_prefix
));
1153 STREAM_GET(&ls_pref
->adv
, s
, sizeof(struct ls_node_id
));
1154 STREAM_GETW(s
, ls_pref
->flags
);
1155 STREAM_GETC(s
, ls_pref
->pref
.family
);
1156 STREAM_GETW(s
, ls_pref
->pref
.prefixlen
);
1157 len
= prefix_blen(&ls_pref
->pref
);
1158 STREAM_GET(&ls_pref
->pref
.u
.prefix
, s
, len
);
1159 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1160 STREAM_GETC(s
, ls_pref
->igp_flag
);
1161 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1162 STREAM_GETL(s
, ls_pref
->route_tag
);
1163 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1164 STREAM_GETQ(s
, ls_pref
->extended_tag
);
1165 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1166 STREAM_GETL(s
, ls_pref
->metric
);
1167 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1168 STREAM_GETL(s
, ls_pref
->sr
.sid
);
1169 STREAM_GETC(s
, ls_pref
->sr
.sid_flag
);
1170 STREAM_GETC(s
, ls_pref
->sr
.algo
);
1176 zlog_err("LS(%s): Could not parse Link State Prefix. Abort!", __func__
);
1177 XFREE(MTYPE_LS_DB
, ls_pref
);
1181 struct ls_message
*ls_parse_msg(struct stream
*s
)
1183 struct ls_message
*msg
;
1185 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1187 /* Read LS Message header */
1188 STREAM_GETC(s
, msg
->event
);
1189 STREAM_GETC(s
, msg
->type
);
1190 STREAM_GET(&msg
->remote_id
, s
, sizeof(struct ls_node_id
));
1192 /* Read Message Payload */
1193 switch (msg
->type
) {
1194 case LS_MSG_TYPE_NODE
:
1195 msg
->data
.node
= ls_parse_node(s
);
1197 case LS_MSG_TYPE_ATTRIBUTES
:
1198 msg
->data
.attr
= ls_parse_attributes(s
);
1200 case LS_MSG_TYPE_PREFIX
:
1201 msg
->data
.prefix
= ls_parse_prefix(s
);
1204 zlog_err("Unsupported Payload");
1205 goto stream_failure
;
1208 if (msg
->data
.node
== NULL
|| msg
->data
.attr
== NULL
1209 || msg
->data
.prefix
== NULL
)
1210 goto stream_failure
;
1215 zlog_err("LS(%s): Could not parse LS message. Abort!", __func__
);
1216 XFREE(MTYPE_LS_DB
, msg
);
1220 static int ls_format_node(struct stream
*s
, struct ls_node
*node
)
1224 /* Push Advertise node information first */
1225 stream_put(s
, &node
->adv
, sizeof(struct ls_node_id
));
1227 /* Push Flags & Origin then Node information if there are present */
1228 stream_putw(s
, node
->flags
);
1229 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1230 len
= strlen(node
->name
);
1231 stream_putc(s
, len
+ 1);
1232 stream_put(s
, node
->name
, len
);
1233 stream_putc(s
, '\0');
1235 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1236 stream_put_ipv4(s
, node
->router_id
.s_addr
);
1237 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1238 stream_put(s
, &node
->router6_id
, IPV6_MAX_BYTELEN
);
1239 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1240 stream_putc(s
, node
->node_flag
);
1241 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1242 stream_putc(s
, node
->type
);
1243 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1244 stream_putl(s
, node
->as_number
);
1245 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1246 stream_putl(s
, node
->srgb
.lower_bound
);
1247 stream_putl(s
, node
->srgb
.range_size
);
1248 stream_putc(s
, node
->srgb
.flag
);
1249 stream_put(s
, node
->algo
, 2);
1251 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1252 stream_putl(s
, node
->srlb
.lower_bound
);
1253 stream_putl(s
, node
->srlb
.range_size
);
1255 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1256 stream_putc(s
, node
->msd
);
1261 static int ls_format_attributes(struct stream
*s
, struct ls_attributes
*attr
)
1265 /* Push Advertise node information first */
1266 stream_put(s
, &attr
->adv
, sizeof(struct ls_node_id
));
1268 /* Push Flags & Origin then LS attributes if there are present */
1269 stream_putl(s
, attr
->flags
);
1270 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1271 len
= strlen(attr
->name
);
1272 stream_putc(s
, len
+ 1);
1273 stream_put(s
, attr
->name
, len
);
1274 stream_putc(s
, '\0');
1276 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1277 stream_putl(s
, attr
->metric
);
1278 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1279 stream_putl(s
, attr
->standard
.te_metric
);
1280 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1281 stream_putl(s
, attr
->standard
.admin_group
);
1282 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1283 stream_put_ipv4(s
, attr
->standard
.local
.s_addr
);
1284 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1285 stream_put_ipv4(s
, attr
->standard
.remote
.s_addr
);
1286 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1287 stream_put(s
, &attr
->standard
.local6
, IPV6_MAX_BYTELEN
);
1288 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1289 stream_put(s
, &attr
->standard
.remote6
, IPV6_MAX_BYTELEN
);
1290 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1291 stream_putl(s
, attr
->standard
.local_id
);
1292 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1293 stream_putl(s
, attr
->standard
.remote_id
);
1294 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1295 stream_putf(s
, attr
->standard
.max_bw
);
1296 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1297 stream_putf(s
, attr
->standard
.max_rsv_bw
);
1298 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1299 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1300 stream_putf(s
, attr
->standard
.unrsv_bw
[len
]);
1301 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1302 stream_putl(s
, attr
->standard
.remote_as
);
1303 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1304 stream_put_ipv4(s
, attr
->standard
.remote_addr
.s_addr
);
1305 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1306 stream_put(s
, &attr
->standard
.remote_addr6
, IPV6_MAX_BYTELEN
);
1307 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1308 stream_putl(s
, attr
->extended
.delay
);
1309 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1310 stream_putl(s
, attr
->extended
.min_delay
);
1311 stream_putl(s
, attr
->extended
.max_delay
);
1313 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1314 stream_putl(s
, attr
->extended
.jitter
);
1315 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1316 stream_putl(s
, attr
->extended
.pkt_loss
);
1317 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1318 stream_putf(s
, attr
->extended
.ava_bw
);
1319 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1320 stream_putf(s
, attr
->extended
.rsv_bw
);
1321 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1322 stream_putf(s
, attr
->extended
.used_bw
);
1323 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1324 stream_putl(s
, attr
->adj_sid
[0].sid
);
1325 stream_putc(s
, attr
->adj_sid
[0].flags
);
1326 stream_putc(s
, attr
->adj_sid
[0].weight
);
1327 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1328 stream_put(s
, attr
->adj_sid
[0].neighbor
.sysid
,
1330 else if (attr
->adv
.origin
== OSPFv2
)
1332 attr
->adj_sid
[0].neighbor
.addr
.s_addr
);
1334 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1335 stream_putl(s
, attr
->adj_sid
[1].sid
);
1336 stream_putc(s
, attr
->adj_sid
[1].flags
);
1337 stream_putc(s
, attr
->adj_sid
[1].weight
);
1338 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1339 stream_put(s
, attr
->adj_sid
[1].neighbor
.sysid
,
1341 else if (attr
->adv
.origin
== OSPFv2
)
1343 attr
->adj_sid
[1].neighbor
.addr
.s_addr
);
1345 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1346 stream_putc(s
, attr
->srlg_len
);
1347 for (len
= 0; len
< attr
->srlg_len
; len
++)
1348 stream_putl(s
, attr
->srlgs
[len
]);
1354 static int ls_format_prefix(struct stream
*s
, struct ls_prefix
*ls_pref
)
1358 /* Push Advertise node information first */
1359 stream_put(s
, &ls_pref
->adv
, sizeof(struct ls_node_id
));
1361 /* Push Flags, Origin & Prefix then information if there are present */
1362 stream_putw(s
, ls_pref
->flags
);
1363 stream_putc(s
, ls_pref
->pref
.family
);
1364 stream_putw(s
, ls_pref
->pref
.prefixlen
);
1365 len
= prefix_blen(&ls_pref
->pref
);
1366 stream_put(s
, &ls_pref
->pref
.u
.prefix
, len
);
1367 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1368 stream_putc(s
, ls_pref
->igp_flag
);
1369 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1370 stream_putl(s
, ls_pref
->route_tag
);
1371 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1372 stream_putq(s
, ls_pref
->extended_tag
);
1373 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1374 stream_putl(s
, ls_pref
->metric
);
1375 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1376 stream_putl(s
, ls_pref
->sr
.sid
);
1377 stream_putc(s
, ls_pref
->sr
.sid_flag
);
1378 stream_putc(s
, ls_pref
->sr
.algo
);
1384 static int ls_format_msg(struct stream
*s
, struct ls_message
*msg
)
1387 /* Prepare Link State header */
1388 stream_putc(s
, msg
->event
);
1389 stream_putc(s
, msg
->type
);
1390 stream_put(s
, &msg
->remote_id
, sizeof(struct ls_node_id
));
1392 /* Add Message Payload */
1393 switch (msg
->type
) {
1394 case LS_MSG_TYPE_NODE
:
1395 return ls_format_node(s
, msg
->data
.node
);
1396 case LS_MSG_TYPE_ATTRIBUTES
:
1397 return ls_format_attributes(s
, msg
->data
.attr
);
1398 case LS_MSG_TYPE_PREFIX
:
1399 return ls_format_prefix(s
, msg
->data
.prefix
);
1401 zlog_warn("Unsupported Payload");
1408 int ls_send_msg(struct zclient
*zclient
, struct ls_message
*msg
,
1409 struct zapi_opaque_reg_info
*dst
)
1414 /* Check if we have a valid message */
1415 if (msg
->event
== LS_MSG_EVENT_UNDEF
)
1418 /* Check buffer size */
1419 if (STREAM_SIZE(zclient
->obuf
) <
1420 (ZEBRA_HEADER_SIZE
+ sizeof(uint32_t) + sizeof(msg
)))
1426 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
1428 /* Set sub-type, flags and destination for unicast message */
1429 stream_putl(s
, LINK_STATE_UPDATE
);
1431 SET_FLAG(flags
, ZAPI_OPAQUE_FLAG_UNICAST
);
1432 stream_putw(s
, flags
);
1433 /* Send destination client info */
1434 stream_putc(s
, dst
->proto
);
1435 stream_putw(s
, dst
->instance
);
1436 stream_putl(s
, dst
->session_id
);
1438 stream_putw(s
, flags
);
1441 /* Format Link State message */
1442 if (ls_format_msg(s
, msg
) < 0) {
1447 /* Put length into the header at the start of the stream. */
1448 stream_putw_at(s
, 0, stream_get_endp(s
));
1450 return zclient_send_message(zclient
);
1453 struct ls_message
*ls_vertex2msg(struct ls_message
*msg
,
1454 struct ls_vertex
*vertex
)
1456 /* Allocate space if needed */
1458 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1460 memset(msg
, 0, sizeof(*msg
));
1462 msg
->type
= LS_MSG_TYPE_NODE
;
1463 switch (vertex
->status
) {
1465 msg
->event
= LS_MSG_EVENT_ADD
;
1468 msg
->event
= LS_MSG_EVENT_UPDATE
;
1471 msg
->event
= LS_MSG_EVENT_DELETE
;
1474 msg
->event
= LS_MSG_EVENT_SYNC
;
1477 msg
->event
= LS_MSG_EVENT_UNDEF
;
1480 msg
->data
.node
= vertex
->node
;
1481 msg
->remote_id
.origin
= UNKNOWN
;
1486 struct ls_message
*ls_edge2msg(struct ls_message
*msg
, struct ls_edge
*edge
)
1488 /* Allocate space if needed */
1490 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1492 memset(msg
, 0, sizeof(*msg
));
1494 msg
->type
= LS_MSG_TYPE_ATTRIBUTES
;
1495 switch (edge
->status
) {
1497 msg
->event
= LS_MSG_EVENT_ADD
;
1500 msg
->event
= LS_MSG_EVENT_UPDATE
;
1503 msg
->event
= LS_MSG_EVENT_DELETE
;
1506 msg
->event
= LS_MSG_EVENT_SYNC
;
1509 msg
->event
= LS_MSG_EVENT_UNDEF
;
1512 msg
->data
.attr
= edge
->attributes
;
1513 if (edge
->destination
!= NULL
)
1514 msg
->remote_id
= edge
->destination
->node
->adv
;
1516 msg
->remote_id
.origin
= UNKNOWN
;
1521 struct ls_message
*ls_subnet2msg(struct ls_message
*msg
,
1522 struct ls_subnet
*subnet
)
1524 /* Allocate space if needed */
1526 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1528 memset(msg
, 0, sizeof(*msg
));
1530 msg
->type
= LS_MSG_TYPE_PREFIX
;
1531 switch (subnet
->status
) {
1533 msg
->event
= LS_MSG_EVENT_ADD
;
1536 msg
->event
= LS_MSG_EVENT_UPDATE
;
1539 msg
->event
= LS_MSG_EVENT_DELETE
;
1542 msg
->event
= LS_MSG_EVENT_SYNC
;
1545 msg
->event
= LS_MSG_EVENT_UNDEF
;
1548 msg
->data
.prefix
= subnet
->ls_pref
;
1549 msg
->remote_id
.origin
= UNKNOWN
;
1554 struct ls_vertex
*ls_msg2vertex(struct ls_ted
*ted
, struct ls_message
*msg
,
1557 struct ls_node
*node
= (struct ls_node
*)msg
->data
.node
;
1558 struct ls_vertex
*vertex
= NULL
;
1560 switch (msg
->event
) {
1561 case LS_MSG_EVENT_SYNC
:
1562 vertex
= ls_vertex_add(ted
, node
);
1564 vertex
->status
= SYNC
;
1566 case LS_MSG_EVENT_ADD
:
1567 vertex
= ls_vertex_add(ted
, node
);
1569 vertex
->status
= NEW
;
1571 case LS_MSG_EVENT_UPDATE
:
1572 vertex
= ls_vertex_update(ted
, node
);
1574 vertex
->status
= UPDATE
;
1576 case LS_MSG_EVENT_DELETE
:
1577 vertex
= ls_find_vertex_by_id(ted
, node
->adv
);
1580 ls_vertex_del_all(ted
, vertex
);
1582 vertex
->status
= DELETE
;
1593 struct ls_edge
*ls_msg2edge(struct ls_ted
*ted
, struct ls_message
*msg
,
1596 struct ls_attributes
*attr
= (struct ls_attributes
*)msg
->data
.attr
;
1597 struct ls_edge
*edge
= NULL
;
1599 switch (msg
->event
) {
1600 case LS_MSG_EVENT_SYNC
:
1601 edge
= ls_edge_add(ted
, attr
);
1603 edge
->status
= SYNC
;
1605 case LS_MSG_EVENT_ADD
:
1606 edge
= ls_edge_add(ted
, attr
);
1610 case LS_MSG_EVENT_UPDATE
:
1611 edge
= ls_edge_update(ted
, attr
);
1613 edge
->status
= UPDATE
;
1615 case LS_MSG_EVENT_DELETE
:
1616 edge
= ls_find_edge_by_source(ted
, attr
);
1619 ls_edge_del_all(ted
, edge
);
1621 edge
->status
= DELETE
;
1632 struct ls_subnet
*ls_msg2subnet(struct ls_ted
*ted
, struct ls_message
*msg
,
1635 struct ls_prefix
*pref
= (struct ls_prefix
*)msg
->data
.prefix
;
1636 struct ls_subnet
*subnet
= NULL
;
1638 switch (msg
->event
) {
1639 case LS_MSG_EVENT_SYNC
:
1640 subnet
= ls_subnet_add(ted
, pref
);
1642 subnet
->status
= SYNC
;
1644 case LS_MSG_EVENT_ADD
:
1645 subnet
= ls_subnet_add(ted
, pref
);
1647 subnet
->status
= NEW
;
1649 case LS_MSG_EVENT_UPDATE
:
1650 subnet
= ls_subnet_update(ted
, pref
);
1652 subnet
->status
= UPDATE
;
1654 case LS_MSG_EVENT_DELETE
:
1655 subnet
= ls_find_subnet(ted
, pref
->pref
);
1658 ls_subnet_del_all(ted
, subnet
);
1660 subnet
->status
= DELETE
;
1671 struct ls_element
*ls_msg2ted(struct ls_ted
*ted
, struct ls_message
*msg
,
1674 struct ls_element
*lse
= NULL
;
1676 switch (msg
->type
) {
1677 case LS_MSG_TYPE_NODE
:
1678 lse
= (struct ls_element
*)ls_msg2vertex(ted
, msg
, delete);
1680 case LS_MSG_TYPE_ATTRIBUTES
:
1681 lse
= (struct ls_element
*)ls_msg2edge(ted
, msg
, delete);
1683 case LS_MSG_TYPE_PREFIX
:
1684 lse
= (struct ls_element
*)ls_msg2subnet(ted
, msg
, delete);
1694 struct ls_element
*ls_stream2ted(struct ls_ted
*ted
, struct stream
*s
,
1697 struct ls_message
*msg
;
1698 struct ls_element
*lse
= NULL
;
1700 msg
= ls_parse_msg(s
);
1702 lse
= ls_msg2ted(ted
, msg
, delete);
1709 void ls_delete_msg(struct ls_message
*msg
)
1714 XFREE(MTYPE_LS_DB
, msg
);
1717 int ls_sync_ted(struct ls_ted
*ted
, struct zclient
*zclient
,
1718 struct zapi_opaque_reg_info
*dst
)
1720 struct ls_vertex
*vertex
;
1721 struct ls_edge
*edge
;
1722 struct ls_subnet
*subnet
;
1723 struct ls_message msg
;
1725 /* Loop TED, start sending Node, then Attributes and finally Prefix */
1726 frr_each(vertices
, &ted
->vertices
, vertex
) {
1727 ls_vertex2msg(&msg
, vertex
);
1728 ls_send_msg(zclient
, &msg
, dst
);
1730 frr_each(edges
, &ted
->edges
, edge
) {
1731 ls_edge2msg(&msg
, edge
);
1732 ls_send_msg(zclient
, &msg
, dst
);
1734 frr_each(subnets
, &ted
->subnets
, subnet
) {
1735 ls_subnet2msg(&msg
, subnet
);
1736 ls_send_msg(zclient
, &msg
, dst
);
1742 * Link State Show functions
1744 static const char *const origin2txt
[] = {
1753 static const char *const type2txt
[] = {
1762 static const char *const status2txt
[] = {
1771 static const char *ls_node_id_to_text(struct ls_node_id lnid
, char *str
,
1774 if (lnid
.origin
== ISIS_L1
|| lnid
.origin
== ISIS_L2
) {
1777 id
= lnid
.id
.iso
.sys_id
;
1778 snprintfrr(str
, size
, "%02x%02x.%02x%02x.%02x%02x", id
[0],
1779 id
[1], id
[2], id
[3], id
[4], id
[5]);
1781 snprintfrr(str
, size
, "%pI4", &lnid
.id
.ip
.addr
);
1786 static void ls_show_vertex_vty(struct ls_vertex
*vertex
, struct vty
*vty
,
1789 struct listnode
*node
;
1790 struct ls_node
*lsn
;
1791 struct ls_edge
*edge
;
1792 struct ls_subnet
*subnet
;
1802 sbuf_init(&sbuf
, NULL
, 0);
1804 sbuf_push(&sbuf
, 2, "Vertex (%" PRIu64
"): %s", vertex
->key
, lsn
->name
);
1805 sbuf_push(&sbuf
, 0, "\tRouter Id: %pI4", &lsn
->router_id
);
1806 sbuf_push(&sbuf
, 0, "\tOrigin: %s", origin2txt
[lsn
->adv
.origin
]);
1807 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[vertex
->status
]);
1811 "\t%d Outgoing Edges, %d Incoming Edges, %d Subnets\n",
1812 listcount(vertex
->outgoing_edges
),
1813 listcount(vertex
->incoming_edges
),
1814 listcount(vertex
->prefixes
));
1818 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
1819 sbuf_push(&sbuf
, 4, "Type: %s\n", type2txt
[lsn
->type
]);
1820 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
1821 sbuf_push(&sbuf
, 4, "AS number: %u\n", lsn
->as_number
);
1822 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
1823 sbuf_push(&sbuf
, 4, "Segment Routing Capabilities:\n");
1824 upper
= lsn
->srgb
.lower_bound
+ lsn
->srgb
.range_size
- 1;
1825 sbuf_push(&sbuf
, 8, "SRGB: [%d/%d]", lsn
->srgb
.lower_bound
,
1827 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
1828 upper
= lsn
->srlb
.lower_bound
+ lsn
->srlb
.range_size
1830 sbuf_push(&sbuf
, 0, "\tSRLB: [%d/%d]",
1831 lsn
->srlb
.lower_bound
, upper
);
1833 sbuf_push(&sbuf
, 0, "\tAlgo: ");
1834 for (int i
= 0; i
< 2; i
++) {
1835 if (lsn
->algo
[i
] == 255)
1839 lsn
->algo
[i
] == 0 ? "SPF " : "S-SPF ");
1841 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
1842 sbuf_push(&sbuf
, 0, "\tMSD: %d", lsn
->msd
);
1843 sbuf_push(&sbuf
, 0, "\n");
1846 sbuf_push(&sbuf
, 4, "Outgoing Edges: %d\n",
1847 listcount(vertex
->outgoing_edges
));
1848 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, node
, edge
)) {
1849 if (edge
->destination
) {
1850 lsn
= edge
->destination
->node
;
1851 sbuf_push(&sbuf
, 6, "To:\t%s(%pI4)", lsn
->name
,
1854 sbuf_push(&sbuf
, 6, "To:\t- (0.0.0.0)");
1856 sbuf_push(&sbuf
, 0, "\tLocal: %pI4\tRemote: %pI4\n",
1857 &edge
->attributes
->standard
.local
,
1858 &edge
->attributes
->standard
.remote
);
1861 sbuf_push(&sbuf
, 4, "Incoming Edges: %d\n",
1862 listcount(vertex
->incoming_edges
));
1863 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, node
, edge
)) {
1865 lsn
= edge
->source
->node
;
1866 sbuf_push(&sbuf
, 6, "From:\t%s(%pI4)", lsn
->name
,
1869 sbuf_push(&sbuf
, 6, "From:\t- (0.0.0.0)");
1871 sbuf_push(&sbuf
, 0, "\tRemote: %pI4\tLocal: %pI4\n",
1872 &edge
->attributes
->standard
.local
,
1873 &edge
->attributes
->standard
.remote
);
1876 sbuf_push(&sbuf
, 4, "Subnets: %d\n", listcount(vertex
->prefixes
));
1877 for (ALL_LIST_ELEMENTS_RO(vertex
->prefixes
, node
, subnet
))
1878 sbuf_push(&sbuf
, 6, "Prefix:\t%pFX\n", &subnet
->key
);
1881 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
1885 static void ls_show_vertex_json(struct ls_vertex
*vertex
,
1886 struct json_object
*json
)
1888 struct ls_node
*lsn
;
1889 json_object
*jsr
, *jalgo
, *jobj
;
1890 char buf
[INET6_BUFSIZ
];
1898 json_object_int_add(json
, "vertex-id", vertex
->key
);
1899 json_object_string_add(json
, "status", status2txt
[vertex
->status
]);
1900 json_object_string_add(json
, "origin", origin2txt
[lsn
->adv
.origin
]);
1901 if (CHECK_FLAG(lsn
->flags
, LS_NODE_NAME
))
1902 json_object_string_add(json
, "name", lsn
->name
);
1903 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID
)) {
1904 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &lsn
->router_id
);
1905 json_object_string_add(json
, "router-id", buf
);
1907 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID6
)) {
1908 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &lsn
->router6_id
);
1909 json_object_string_add(json
, "router-id-v6", buf
);
1911 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
1912 json_object_string_add(json
, "vertex-type",
1913 type2txt
[lsn
->type
]);
1914 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
1915 json_object_int_add(json
, "asn", lsn
->as_number
);
1916 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
1917 jsr
= json_object_new_object();
1918 json_object_object_add(json
, "segment-routing", jsr
);
1919 json_object_int_add(jsr
, "srgb-size", lsn
->srgb
.range_size
);
1920 json_object_int_add(jsr
, "srgb-lower", lsn
->srgb
.lower_bound
);
1921 jalgo
= json_object_new_array();
1922 json_object_object_add(jsr
, "algorithms", jalgo
);
1923 for (int i
= 0; i
< 2; i
++) {
1924 if (lsn
->algo
[i
] == 255)
1926 jobj
= json_object_new_object();
1928 snprintfrr(buf
, 2, "%u", i
);
1929 json_object_string_add(
1930 jobj
, buf
, lsn
->algo
[i
] == 0 ? "SPF" : "S-SPF");
1931 json_object_array_add(jalgo
, jobj
);
1933 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
1934 json_object_int_add(jsr
, "srlb-size",
1935 lsn
->srlb
.range_size
);
1936 json_object_int_add(jsr
, "srlb-lower",
1937 lsn
->srlb
.lower_bound
);
1939 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
1940 json_object_int_add(jsr
, "msd", lsn
->msd
);
1944 void ls_show_vertex(struct ls_vertex
*vertex
, struct vty
*vty
,
1945 struct json_object
*json
, bool verbose
)
1948 ls_show_vertex_json(vertex
, json
);
1950 ls_show_vertex_vty(vertex
, vty
, verbose
);
1953 void ls_show_vertices(struct ls_ted
*ted
, struct vty
*vty
,
1954 struct json_object
*json
, bool verbose
)
1956 struct ls_vertex
*vertex
;
1957 json_object
*jnodes
, *jnode
;
1960 jnodes
= json_object_new_array();
1961 json_object_object_add(json
, "vertices", jnodes
);
1962 frr_each (vertices
, &ted
->vertices
, vertex
) {
1963 jnode
= json_object_new_object();
1964 ls_show_vertex(vertex
, NULL
, jnode
, verbose
);
1965 json_object_array_add(jnodes
, jnode
);
1968 frr_each (vertices
, &ted
->vertices
, vertex
)
1969 ls_show_vertex(vertex
, vty
, NULL
, verbose
);
1973 static void ls_show_edge_vty(struct ls_edge
*edge
, struct vty
*vty
,
1976 struct ls_attributes
*attr
;
1978 char buf
[INET6_BUFSIZ
];
1980 attr
= edge
->attributes
;
1981 sbuf_init(&sbuf
, NULL
, 0);
1983 sbuf_push(&sbuf
, 2, "Edge (%" PRIu64
"): ", edge
->key
);
1984 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1985 sbuf_push(&sbuf
, 0, "%pI4", &attr
->standard
.local
);
1986 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1987 sbuf_push(&sbuf
, 0, "%pI6", &attr
->standard
.local6
);
1989 sbuf_push(&sbuf
, 0, "%u/%u", attr
->standard
.local_id
,
1990 attr
->standard
.remote_id
);
1991 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
1992 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
1993 sbuf_push(&sbuf
, 0, "\tMetric: %u", attr
->metric
);
1994 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[edge
->status
]);
1999 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[attr
->adv
.origin
]);
2000 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2001 sbuf_push(&sbuf
, 4, "Name: %s\n", attr
->name
);
2002 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2003 sbuf_push(&sbuf
, 4, "TE Metric: %u\n",
2004 attr
->standard
.te_metric
);
2005 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2006 sbuf_push(&sbuf
, 4, "Admin Group: 0x%x\n",
2007 attr
->standard
.admin_group
);
2008 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
2009 sbuf_push(&sbuf
, 4, "Local IPv4 address: %pI4\n",
2010 &attr
->standard
.local
);
2011 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
2012 sbuf_push(&sbuf
, 4, "Remote IPv4 address: %pI4\n",
2013 &attr
->standard
.remote
);
2014 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
2015 sbuf_push(&sbuf
, 4, "Local IPv6 address: %pI6\n",
2016 &attr
->standard
.local6
);
2017 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
2018 sbuf_push(&sbuf
, 4, "Remote IPv6 address: %pI6\n",
2019 &attr
->standard
.remote6
);
2020 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2021 sbuf_push(&sbuf
, 4, "Local Identifier: %u\n",
2022 attr
->standard
.local_id
);
2023 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2024 sbuf_push(&sbuf
, 4, "Remote Identifier: %u\n",
2025 attr
->standard
.remote_id
);
2026 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2027 sbuf_push(&sbuf
, 4, "Maximum Bandwidth: %g (Bytes/s)\n",
2028 attr
->standard
.max_bw
);
2029 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2031 "Maximum Reservable Bandwidth: %g (Bytes/s)\n",
2032 attr
->standard
.max_rsv_bw
);
2033 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2034 sbuf_push(&sbuf
, 4, "Unreserved Bandwidth per Class Type\n");
2035 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
+= 2)
2037 "[%d]: %g (Bytes/sec)\t[%d]: %g (Bytes/s)\n",
2038 i
, attr
->standard
.unrsv_bw
[i
], i
+ 1,
2039 attr
->standard
.unrsv_bw
[i
+ 1]);
2041 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2042 sbuf_push(&sbuf
, 4, "Remote AS: %u\n",
2043 attr
->standard
.remote_as
);
2044 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
2045 sbuf_push(&sbuf
, 4, "Remote ASBR IPv4 address: %pI4\n",
2046 &attr
->standard
.remote_addr
);
2047 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
2048 sbuf_push(&sbuf
, 4, "Remote ASBR IPv6 address: %pI6\n",
2049 &attr
->standard
.remote_addr6
);
2050 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2051 sbuf_push(&sbuf
, 4, "Average Link Delay: %d (micro-sec)\n",
2052 attr
->extended
.delay
);
2053 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
))
2054 sbuf_push(&sbuf
, 4, "Min/Max Link Delay: %d/%d (micro-sec)\n",
2055 attr
->extended
.min_delay
, attr
->extended
.max_delay
);
2056 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2057 sbuf_push(&sbuf
, 4, "Delay Variation: %d (micro-sec)\n",
2058 attr
->extended
.jitter
);
2059 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2060 sbuf_push(&sbuf
, 4, "Link Loss: %g (%%)\n",
2061 (float)(attr
->extended
.pkt_loss
* LOSS_PRECISION
));
2062 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2063 sbuf_push(&sbuf
, 4, "Available Bandwidth: %g (Bytes/s)\n",
2064 attr
->extended
.ava_bw
);
2065 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2066 sbuf_push(&sbuf
, 4, "Residual Bandwidth: %g (Bytes/s)\n",
2067 attr
->extended
.rsv_bw
);
2068 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2069 sbuf_push(&sbuf
, 4, "Utilized Bandwidth: %g (Bytes/s)\n",
2070 attr
->extended
.used_bw
);
2071 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2072 sbuf_push(&sbuf
, 4, "Adjacency-SID: %u", attr
->adj_sid
[0].sid
);
2073 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2074 attr
->adj_sid
[0].flags
, attr
->adj_sid
[0].weight
);
2076 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2077 sbuf_push(&sbuf
, 4, "Bck. Adjacency-SID: %u",
2078 attr
->adj_sid
[1].sid
);
2079 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2080 attr
->adj_sid
[1].flags
, attr
->adj_sid
[1].weight
);
2082 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2083 sbuf_push(&sbuf
, 4, "SRLGs: %d", attr
->srlg_len
);
2084 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2086 sbuf_push(&sbuf
, 8, "\n%u", attr
->srlgs
[i
]);
2088 sbuf_push(&sbuf
, 8, ", %u", attr
->srlgs
[i
]);
2090 sbuf_push(&sbuf
, 0, "\n");
2094 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2098 static void ls_show_edge_json(struct ls_edge
*edge
, struct json_object
*json
)
2100 struct ls_attributes
*attr
;
2101 struct json_object
*jte
, *jbw
, *jobj
, *jsr
= NULL
, *jsrlg
;
2102 char buf
[INET6_BUFSIZ
];
2104 attr
= edge
->attributes
;
2106 json_object_int_add(json
, "edge-id", edge
->key
);
2107 json_object_string_add(json
, "status", status2txt
[edge
->status
]);
2108 json_object_string_add(json
, "origin", origin2txt
[attr
->adv
.origin
]);
2109 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
2110 json_object_string_add(json
, "advertised-router", buf
);
2112 json_object_int_add(json
, "local-vertex-id", edge
->source
->key
);
2113 if (edge
->destination
)
2114 json_object_int_add(json
, "remote-vertex-id",
2115 edge
->destination
->key
);
2116 json_object_int_add(json
, "metric", attr
->metric
);
2117 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2118 json_object_string_add(json
, "name", attr
->name
);
2119 jte
= json_object_new_object();
2120 json_object_object_add(json
, "edge-attributes", jte
);
2121 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2122 json_object_int_add(jte
, "te-metric", attr
->standard
.te_metric
);
2123 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2124 json_object_int_add(jte
, "admin-group",
2125 attr
->standard
.admin_group
);
2126 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)) {
2127 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.local
);
2128 json_object_string_add(jte
, "local-address", buf
);
2130 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
)) {
2131 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.remote
);
2132 json_object_string_add(jte
, "remote-address", buf
);
2134 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)) {
2135 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.local6
);
2136 json_object_string_add(jte
, "local-address-v6", buf
);
2138 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
)) {
2139 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.remote6
);
2140 json_object_string_add(jte
, "remote-address-v6", buf
);
2142 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2143 json_object_int_add(jte
, "local-identifier",
2144 attr
->standard
.local_id
);
2145 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2146 json_object_int_add(jte
, "remote-identifier",
2147 attr
->standard
.remote_id
);
2148 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2149 json_object_double_add(jte
, "max-link-bandwidth",
2150 attr
->standard
.max_bw
);
2151 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2152 json_object_double_add(jte
, "max-resv-link-bandwidth",
2153 attr
->standard
.max_rsv_bw
);
2154 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2155 jbw
= json_object_new_array();
2156 json_object_object_add(jte
, "unreserved-bandwidth", jbw
);
2157 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
++) {
2158 jobj
= json_object_new_object();
2159 snprintfrr(buf
, 13, "class-type-%u", i
);
2160 json_object_double_add(jobj
, buf
,
2161 attr
->standard
.unrsv_bw
[i
]);
2162 json_object_array_add(jbw
, jobj
);
2165 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2166 json_object_int_add(jte
, "remote-asn",
2167 attr
->standard
.remote_as
);
2168 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
)) {
2169 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4",
2170 &attr
->standard
.remote_addr
);
2171 json_object_string_add(jte
, "remote-as-address", buf
);
2173 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
)) {
2174 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6",
2175 &attr
->standard
.remote_addr6
);
2176 json_object_string_add(jte
, "remote-as-address-v6", buf
);
2178 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2179 json_object_int_add(jte
, "delay", attr
->extended
.delay
);
2180 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
2181 json_object_int_add(jte
, "min-delay", attr
->extended
.min_delay
);
2182 json_object_int_add(jte
, "max-delay", attr
->extended
.max_delay
);
2184 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2185 json_object_int_add(jte
, "jitter", attr
->extended
.jitter
);
2186 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2187 json_object_double_add(
2188 jte
, "loss", attr
->extended
.pkt_loss
* LOSS_PRECISION
);
2189 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2190 json_object_double_add(jte
, "available-bandwidth",
2191 attr
->extended
.ava_bw
);
2192 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2193 json_object_double_add(jte
, "residual-bandwidth",
2194 attr
->extended
.rsv_bw
);
2195 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2196 json_object_double_add(jte
, "utilized-bandwidth",
2197 attr
->extended
.used_bw
);
2198 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2199 jsrlg
= json_object_new_array();
2200 json_object_object_add(jte
, "srlgs", jsrlg
);
2201 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2202 jobj
= json_object_new_object();
2203 json_object_int_add(jobj
, "srlg", attr
->srlgs
[i
]);
2204 json_object_array_add(jsrlg
, jobj
);
2207 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2208 jsr
= json_object_new_array();
2209 json_object_object_add(json
, "segment-routing", jsr
);
2210 jobj
= json_object_new_object();
2211 json_object_int_add(jobj
, "adj-sid", attr
->adj_sid
[0].sid
);
2212 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[0].flags
);
2213 json_object_string_add(jobj
, "flags", buf
);
2214 json_object_int_add(jobj
, "weight", attr
->adj_sid
[0].weight
);
2215 json_object_array_add(jsr
, jobj
);
2217 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2219 jsr
= json_object_new_array();
2220 json_object_object_add(json
, "segment-routing", jsr
);
2222 jobj
= json_object_new_object();
2223 json_object_int_add(jobj
, "adj-sid", attr
->adj_sid
[1].sid
);
2224 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[1].flags
);
2225 json_object_string_add(jobj
, "flags", buf
);
2226 json_object_int_add(jobj
, "weight", attr
->adj_sid
[1].weight
);
2227 json_object_array_add(jsr
, jobj
);
2231 void ls_show_edge(struct ls_edge
*edge
, struct vty
*vty
,
2232 struct json_object
*json
, bool verbose
)
2239 ls_show_edge_json(edge
, json
);
2241 ls_show_edge_vty(edge
, vty
, verbose
);
2244 void ls_show_edges(struct ls_ted
*ted
, struct vty
*vty
,
2245 struct json_object
*json
, bool verbose
)
2247 struct ls_edge
*edge
;
2248 json_object
*jedges
, *jedge
;
2251 jedges
= json_object_new_array();
2252 json_object_object_add(json
, "edges", jedges
);
2253 frr_each (edges
, &ted
->edges
, edge
) {
2254 jedge
= json_object_new_object();
2255 ls_show_edge(edge
, NULL
, jedge
, verbose
);
2256 json_object_array_add(jedges
, jedge
);
2259 frr_each (edges
, &ted
->edges
, edge
)
2260 ls_show_edge(edge
, vty
, NULL
, verbose
);
2264 static void ls_show_subnet_vty(struct ls_subnet
*subnet
, struct vty
*vty
,
2267 struct ls_prefix
*pref
;
2269 char buf
[INET6_BUFSIZ
];
2271 pref
= subnet
->ls_pref
;
2272 sbuf_init(&sbuf
, NULL
, 0);
2274 sbuf_push(&sbuf
, 2, "Subnet: %pFX", &subnet
->key
);
2275 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2276 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
2277 sbuf_push(&sbuf
, 0, "\tMetric: %d", pref
->metric
);
2278 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[subnet
->status
]);
2283 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[pref
->adv
.origin
]);
2284 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
))
2285 sbuf_push(&sbuf
, 4, "Flags: %d\n", pref
->igp_flag
);
2287 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2288 sbuf_push(&sbuf
, 4, "Tag: %d\n", pref
->route_tag
);
2290 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2291 sbuf_push(&sbuf
, 4, "Extended Tag: %" PRIu64
"\n",
2292 pref
->extended_tag
);
2294 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
))
2295 sbuf_push(&sbuf
, 4, "SID: %d\tAlgorithm: %d\tFlags: 0x%x\n",
2296 pref
->sr
.sid
, pref
->sr
.algo
, pref
->sr
.sid_flag
);
2299 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2303 static void ls_show_subnet_json(struct ls_subnet
*subnet
,
2304 struct json_object
*json
)
2306 struct ls_prefix
*pref
;
2308 char buf
[INET6_BUFSIZ
];
2310 pref
= subnet
->ls_pref
;
2312 snprintfrr(buf
, INET6_BUFSIZ
, "%pFX", &subnet
->key
);
2313 json_object_string_add(json
, "subnet-id", buf
);
2314 json_object_string_add(json
, "status", status2txt
[subnet
->status
]);
2315 json_object_string_add(json
, "origin", origin2txt
[pref
->adv
.origin
]);
2316 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2317 json_object_string_add(json
, "advertised-router", buf
);
2319 json_object_int_add(json
, "vertex-id", subnet
->vertex
->key
);
2320 json_object_int_add(json
, "metric", pref
->metric
);
2321 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
)) {
2322 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->igp_flag
);
2323 json_object_string_add(json
, "flags", buf
);
2325 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2326 json_object_int_add(json
, "tag", pref
->route_tag
);
2327 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2328 json_object_int_add(json
, "extended-tag", pref
->extended_tag
);
2329 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
)) {
2330 jsr
= json_object_new_object();
2331 json_object_object_add(json
, "segment-routing", jsr
);
2332 json_object_int_add(jsr
, "pref-sid", pref
->sr
.sid
);
2333 json_object_int_add(jsr
, "algo", pref
->sr
.algo
);
2334 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->sr
.sid_flag
);
2335 json_object_string_add(jsr
, "flags", buf
);
2339 void ls_show_subnet(struct ls_subnet
*subnet
, struct vty
*vty
,
2340 struct json_object
*json
, bool verbose
)
2347 ls_show_subnet_json(subnet
, json
);
2349 ls_show_subnet_vty(subnet
, vty
, verbose
);
2352 void ls_show_subnets(struct ls_ted
*ted
, struct vty
*vty
,
2353 struct json_object
*json
, bool verbose
)
2355 struct ls_subnet
*subnet
;
2356 json_object
*jsubs
, *jsub
;
2359 jsubs
= json_object_new_array();
2360 json_object_object_add(json
, "subnets", jsubs
);
2361 frr_each (subnets
, &ted
->subnets
, subnet
) {
2362 jsub
= json_object_new_object();
2363 ls_show_subnet(subnet
, NULL
, jsub
, verbose
);
2364 json_object_array_add(jsubs
, jsub
);
2367 frr_each (subnets
, &ted
->subnets
, subnet
)
2368 ls_show_subnet(subnet
, vty
, NULL
, verbose
);
2372 void ls_show_ted(struct ls_ted
*ted
, struct vty
*vty
, struct json_object
*json
,
2378 jted
= json_object_new_object();
2379 json_object_object_add(json
, "ted", jted
);
2380 json_object_string_add(jted
, "name", ted
->name
);
2381 json_object_int_add(jted
, "key", ted
->key
);
2382 json_object_int_add(jted
, "verticesCount",
2383 vertices_count(&ted
->vertices
));
2384 json_object_int_add(jted
, "edgesCount",
2385 edges_count(&ted
->edges
));
2386 json_object_int_add(jted
, "subnetsCount",
2387 subnets_count(&ted
->subnets
));
2388 ls_show_vertices(ted
, NULL
, jted
, verbose
);
2389 ls_show_edges(ted
, NULL
, jted
, verbose
);
2390 ls_show_subnets(ted
, NULL
, jted
, verbose
);
2396 "\n\tTraffic Engineering Database: %s (key: %d)\n\n",
2397 ted
->name
, ted
->key
);
2398 ls_show_vertices(ted
, vty
, NULL
, verbose
);
2399 ls_show_edges(ted
, vty
, NULL
, verbose
);
2400 ls_show_subnets(ted
, vty
, NULL
, verbose
);
2402 "\n\tTotal: %zu Vertices, %zu Edges, %zu Subnets\n\n",
2403 vertices_count(&ted
->vertices
),
2404 edges_count(&ted
->edges
), subnets_count(&ted
->subnets
));
2408 void ls_dump_ted(struct ls_ted
*ted
)
2410 struct ls_vertex
*vertex
;
2411 struct ls_edge
*edge
;
2412 struct ls_subnet
*subnet
;
2413 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
2415 zlog_debug("(%s) Ted init", __func__
);
2417 /* Loop TED, start printing Node, then Attributes and finally Prefix */
2418 frr_each (vertices
, &ted
->vertices
, vertex
) {
2419 zlog_debug(" Ted node (%s %pI4 %s)",
2420 vertex
->node
->name
[0] ? vertex
->node
->name
2422 &vertex
->node
->router_id
,
2423 origin2txt
[vertex
->node
->adv
.origin
]);
2424 struct listnode
*lst_node
;
2425 struct ls_edge
*vertex_edge
;
2427 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, lst_node
,
2430 " inc edge key:%" PRIu64
" attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2432 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2433 &vertex_edge
->attributes
->standard
.local
,
2434 &vertex_edge
->attributes
->standard
.remote
);
2436 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, lst_node
,
2439 " out edge key:%" PRIu64
" attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2441 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2442 &vertex_edge
->attributes
->standard
.local
,
2443 &vertex_edge
->attributes
->standard
.remote
);
2446 frr_each (edges
, &ted
->edges
, edge
) {
2447 zlog_debug(" Ted edge key:%" PRIu64
"src:%pI4 dst:%pI4", edge
->key
,
2448 edge
->source
? &edge
->source
->node
->router_id
2451 ? &edge
->destination
->node
->router_id
2454 frr_each (subnets
, &ted
->subnets
, subnet
) {
2455 zlog_debug(" Ted subnet key:%pFX vertex:%pI4",
2456 &subnet
->ls_pref
->pref
,
2457 &subnet
->vertex
->node
->adv
.id
.ip
.addr
);
2459 zlog_debug("(%s) Ted end", __func__
);