]>
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
29 #include "termtable.h"
39 #include "link_state.h"
41 /* Link State Memory allocation */
42 DEFINE_MTYPE_STATIC(LIB
, LS_DB
, "Link State Database");
45 * Link State Node management functions
47 struct ls_node
*ls_node_new(struct ls_node_id adv
, struct in_addr rid
,
52 if (adv
.origin
== UNKNOWN
)
55 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
57 if (!IPV4_NET0(rid
.s_addr
)) {
59 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID
);
61 if (adv
.origin
== OSPFv2
|| adv
.origin
== STATIC
62 || adv
.origin
== DIRECT
) {
63 new->router_id
= adv
.id
.ip
.addr
;
64 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID
);
67 if (!IN6_IS_ADDR_UNSPECIFIED(&rid6
)) {
68 new->router6_id
= rid6
;
69 SET_FLAG(new->flags
, LS_NODE_ROUTER_ID6
);
74 void ls_node_del(struct ls_node
*node
)
79 XFREE(MTYPE_LS_DB
, node
);
83 int ls_node_same(struct ls_node
*n1
, struct ls_node
*n2
)
85 if ((n1
&& !n2
) || (!n1
&& n2
))
91 if (n1
->flags
!= n2
->flags
)
94 if (n1
->adv
.origin
!= n2
->adv
.origin
)
97 if (!memcmp(&n1
->adv
.id
, &n2
->adv
.id
, sizeof(struct ls_node_id
)))
100 /* Do we need to test individually each field, instead performing a
101 * global memcmp? There is a risk that an old value that is bit masked
102 * i.e. corresponding flag = 0, will result into a false negative
104 if (!memcmp(n1
, n2
, sizeof(struct ls_node
)))
111 * Link State Attributes management functions
113 struct ls_attributes
*ls_attributes_new(struct ls_node_id adv
,
114 struct in_addr local
,
115 struct in6_addr local6
,
118 struct ls_attributes
*new;
120 if (adv
.origin
== UNKNOWN
)
123 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
125 if (!IPV4_NET0(local
.s_addr
)) {
126 new->standard
.local
= local
;
127 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
);
129 if (!IN6_IS_ADDR_UNSPECIFIED(&local6
)) {
130 new->standard
.local6
= local6
;
131 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR6
);
134 new->standard
.local_id
= local_id
;
135 SET_FLAG(new->flags
, LS_ATTR_LOCAL_ID
);
138 /* Check that almost one identifier is set */
139 if (!CHECK_FLAG(new->flags
, LS_ATTR_LOCAL_ADDR
| LS_ATTR_LOCAL_ADDR6
140 | LS_ATTR_LOCAL_ID
)) {
141 XFREE(MTYPE_LS_DB
, new);
148 void ls_attributes_srlg_del(struct ls_attributes
*attr
)
154 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
158 UNSET_FLAG(attr
->flags
, LS_ATTR_SRLG
);
161 void ls_attributes_del(struct ls_attributes
*attr
)
166 ls_attributes_srlg_del(attr
);
168 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
);
225 int ls_prefix_same(struct ls_prefix
*p1
, struct ls_prefix
*p2
)
227 if ((p1
&& !p2
) || (!p1
&& p2
))
233 if (p1
->flags
!= p2
->flags
)
236 if (p1
->adv
.origin
!= p2
->adv
.origin
)
239 if (!memcmp(&p1
->adv
.id
, &p2
->adv
.id
, sizeof(struct ls_node_id
)))
242 /* Do we need to test individually each field, instead performing a
243 * global memcmp? There is a risk that an old value that is bit masked
244 * i.e. corresponding flag = 0, will result into a false negative
246 if (!memcmp(p1
, p2
, sizeof(struct ls_prefix
)))
253 * Link State Vertices management functions
255 struct ls_vertex
*ls_vertex_add(struct ls_ted
*ted
, struct ls_node
*node
)
257 struct ls_vertex
*new;
260 if ((ted
== NULL
) || (node
== NULL
))
263 /* set Key as the IPv4/Ipv6 Router ID or ISO System ID */
264 switch (node
->adv
.origin
) {
268 key
= ((uint64_t)ntohl(node
->adv
.id
.ip
.addr
.s_addr
))
273 memcpy(&key
, &node
->adv
.id
.iso
.sys_id
, ISO_SYS_ID_LEN
);
280 /* Check that key is valid */
284 /* Create Vertex and add it to the TED */
285 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_vertex
));
293 new->incoming_edges
= list_new();
294 new->incoming_edges
->cmp
= (int (*)(void *, void *))edge_cmp
;
295 new->outgoing_edges
= list_new();
296 new->outgoing_edges
->cmp
= (int (*)(void *, void *))edge_cmp
;
297 new->prefixes
= list_new();
298 new->prefixes
->cmp
= (int (*)(void *, void *))subnet_cmp
;
299 vertices_add(&ted
->vertices
, new);
304 void ls_vertex_del(struct ls_ted
*ted
, struct ls_vertex
*vertex
)
306 struct listnode
*node
, *nnode
;
307 struct ls_edge
*edge
;
308 struct ls_subnet
*subnet
;
313 /* Remove outgoing Edges and list */
314 for (ALL_LIST_ELEMENTS(vertex
->outgoing_edges
, node
, nnode
, edge
))
315 ls_edge_del_all(ted
, edge
);
316 list_delete(&vertex
->outgoing_edges
);
318 /* Disconnect incoming Edges and remove list */
319 for (ALL_LIST_ELEMENTS(vertex
->incoming_edges
, node
, nnode
, edge
)) {
320 ls_disconnect(vertex
, edge
, false);
321 if (edge
->source
== NULL
)
322 ls_edge_del_all(ted
, edge
);
324 list_delete(&vertex
->incoming_edges
);
326 /* Remove subnet and list */
327 for (ALL_LIST_ELEMENTS(vertex
->prefixes
, node
, nnode
, subnet
))
328 ls_subnet_del_all(ted
, subnet
);
329 list_delete(&vertex
->prefixes
);
331 /* Then remove Vertex from Link State Data Base and free memory */
332 vertices_del(&ted
->vertices
, vertex
);
333 XFREE(MTYPE_LS_DB
, vertex
);
337 void ls_vertex_del_all(struct ls_ted
*ted
, struct ls_vertex
*vertex
)
342 /* First remove associated Link State Node */
343 ls_node_del(vertex
->node
);
345 /* Then, Vertex itself */
346 ls_vertex_del(ted
, vertex
);
349 struct ls_vertex
*ls_vertex_update(struct ls_ted
*ted
, struct ls_node
*node
)
351 struct ls_vertex
*old
;
356 old
= ls_find_vertex_by_id(ted
, node
->adv
);
358 if (!ls_node_same(old
->node
, node
)) {
359 ls_node_del(old
->node
);
362 old
->status
= UPDATE
;
366 return ls_vertex_add(ted
, node
);
369 struct ls_vertex
*ls_find_vertex_by_key(struct ls_ted
*ted
, const uint64_t key
)
371 struct ls_vertex vertex
= {};
377 return vertices_find(&ted
->vertices
, &vertex
);
380 struct ls_vertex
*ls_find_vertex_by_id(struct ls_ted
*ted
,
381 struct ls_node_id nid
)
383 struct ls_vertex vertex
= {};
386 switch (nid
.origin
) {
391 ((uint64_t)ntohl(nid
.id
.ip
.addr
.s_addr
)) & 0xffffffff;
395 memcpy(&vertex
.key
, &nid
.id
.iso
.sys_id
, ISO_SYS_ID_LEN
);
401 return vertices_find(&ted
->vertices
, &vertex
);
404 int ls_vertex_same(struct ls_vertex
*v1
, struct ls_vertex
*v2
)
406 if ((v1
&& !v2
) || (!v1
&& v2
))
412 if (v1
->key
!= v2
->key
)
415 if (v1
->node
== v2
->node
)
418 return ls_node_same(v1
->node
, v2
->node
);
421 void ls_vertex_clean(struct ls_ted
*ted
, struct ls_vertex
*vertex
,
422 struct zclient
*zclient
)
424 struct listnode
*node
, *nnode
;
425 struct ls_edge
*edge
;
426 struct ls_subnet
*subnet
;
427 struct ls_message msg
;
429 /* Remove Orphan Edge ... */
430 for (ALL_LIST_ELEMENTS(vertex
->outgoing_edges
, node
, nnode
, edge
)) {
431 if (edge
->status
== ORPHAN
) {
433 edge
->status
= DELETE
;
434 ls_edge2msg(&msg
, edge
);
435 ls_send_msg(zclient
, &msg
, NULL
);
437 ls_edge_del_all(ted
, edge
);
440 for (ALL_LIST_ELEMENTS(vertex
->incoming_edges
, node
, nnode
, edge
)) {
441 if (edge
->status
== ORPHAN
) {
443 edge
->status
= DELETE
;
444 ls_edge2msg(&msg
, edge
);
445 ls_send_msg(zclient
, &msg
, NULL
);
447 ls_edge_del_all(ted
, edge
);
451 /* ... and Subnet from the Vertex */
452 for (ALL_LIST_ELEMENTS(vertex
->prefixes
, node
, nnode
, subnet
)) {
453 if (subnet
->status
== ORPHAN
) {
455 subnet
->status
= DELETE
;
456 ls_subnet2msg(&msg
, subnet
);
457 ls_send_msg(zclient
, &msg
, NULL
);
459 ls_subnet_del_all(ted
, subnet
);
465 * Link State Edges management functions
469 * This function allows to connect the Edge to the vertices present in the TED.
470 * A temporary vertex that corresponds to the source of this Edge i.e. the
471 * advertised router, is created if not found in the Data Base. If a Edge that
472 * corresponds to the reverse path is found, the Edge is attached to the
473 * destination vertex as destination and reverse Edge is attached to the source
476 * @param ted Link State Data Base
477 * @param edge Link State Edge to be attached
479 static void ls_edge_connect_to(struct ls_ted
*ted
, struct ls_edge
*edge
)
481 struct ls_vertex
*vertex
= NULL
;
482 struct ls_node
*node
;
484 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
486 /* First, search if there is a Vertex that correspond to the Node ID */
487 vertex
= ls_find_vertex_by_id(ted
, edge
->attributes
->adv
);
488 if (vertex
== NULL
) {
489 /* Create a new temporary Node & Vertex if not found */
490 node
= ls_node_new(edge
->attributes
->adv
, inaddr_any
,
492 vertex
= ls_vertex_add(ted
, node
);
494 /* and attach the edge as source to the vertex */
495 listnode_add_sort_nodup(vertex
->outgoing_edges
, edge
);
496 edge
->source
= vertex
;
498 /* Then search if there is a reverse Edge */
499 dst
= ls_find_edge_by_destination(ted
, edge
->attributes
);
500 /* attach the destination edge to the vertex */
502 listnode_add_sort_nodup(vertex
->incoming_edges
, dst
);
503 dst
->destination
= vertex
;
504 /* and destination vertex to this edge */
505 vertex
= dst
->source
;
506 listnode_add_sort_nodup(vertex
->incoming_edges
, edge
);
507 edge
->destination
= vertex
;
511 struct ls_edge
*ls_edge_add(struct ls_ted
*ted
,
512 struct ls_attributes
*attributes
)
517 if (attributes
== NULL
)
520 /* Key is the IPv4 local address */
521 if (!IPV4_NET0(attributes
->standard
.local
.s_addr
))
522 key
= ((uint64_t)ntohl(attributes
->standard
.local
.s_addr
))
524 /* or the IPv6 local address if IPv4 is not defined */
525 else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes
->standard
.local6
))
526 key
= (uint64_t)(attributes
->standard
.local6
.s6_addr32
[0]
528 | ((uint64_t)attributes
->standard
.local6
.s6_addr32
[1]
530 /* of local identifier if no IP addresses are defined */
531 else if (attributes
->standard
.local_id
!= 0)
533 (attributes
->standard
.local_id
& 0xffffffff)
534 | ((uint64_t)attributes
->standard
.remote_id
<< 32));
536 /* Check that key is valid */
540 /* Create Edge and add it to the TED */
541 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_edge
));
545 new->attributes
= attributes
;
549 edges_add(&ted
->edges
, new);
551 /* Finally, connect Edge to Vertices */
552 ls_edge_connect_to(ted
, new);
557 struct ls_edge
*ls_find_edge_by_key(struct ls_ted
*ted
, const uint64_t key
)
559 struct ls_edge edge
= {};
565 return edges_find(&ted
->edges
, &edge
);
568 struct ls_edge
*ls_find_edge_by_source(struct ls_ted
*ted
,
569 struct ls_attributes
*attributes
)
571 struct ls_edge edge
= {};
573 if (attributes
== NULL
)
577 /* Key is the IPv4 local address */
578 if (!IPV4_NET0(attributes
->standard
.local
.s_addr
))
579 edge
.key
= ((uint64_t)ntohl(attributes
->standard
.local
.s_addr
))
581 /* or the IPv6 local address if IPv4 is not defined */
582 else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes
->standard
.local6
))
583 edge
.key
= (uint64_t)(attributes
->standard
.local6
.s6_addr32
[0]
585 | ((uint64_t)attributes
->standard
.local6
.s6_addr32
[1]
587 /* of local identifier if no IP addresses are defined */
588 else if (attributes
->standard
.local_id
!= 0)
589 edge
.key
= (uint64_t)(
590 (attributes
->standard
.local_id
& 0xffffffff)
591 | ((uint64_t)attributes
->standard
.remote_id
<< 32));
596 return edges_find(&ted
->edges
, &edge
);
599 struct ls_edge
*ls_find_edge_by_destination(struct ls_ted
*ted
,
600 struct ls_attributes
*attributes
)
602 struct ls_edge edge
= {};
604 if (attributes
== NULL
)
608 /* Key is the IPv4 remote address */
609 if (!IPV4_NET0(attributes
->standard
.remote
.s_addr
))
610 edge
.key
= ((uint64_t)ntohl(attributes
->standard
.remote
.s_addr
))
612 /* or the IPv6 remote address if IPv4 is not defined */
613 else if (!IN6_IS_ADDR_UNSPECIFIED(&attributes
->standard
.remote6
))
615 (uint64_t)(attributes
->standard
.remote6
.s6_addr32
[0]
617 | ((uint64_t)attributes
->standard
.remote6
.s6_addr32
[1]
619 /* of remote identifier if no IP addresses are defined */
620 else if (attributes
->standard
.remote_id
!= 0)
621 edge
.key
= (uint64_t)(
622 (attributes
->standard
.remote_id
& 0xffffffff)
623 | ((uint64_t)attributes
->standard
.local_id
<< 32));
628 return edges_find(&ted
->edges
, &edge
);
631 struct ls_edge
*ls_edge_update(struct ls_ted
*ted
,
632 struct ls_attributes
*attributes
)
636 if (attributes
== NULL
)
639 /* First, search for an existing Edge */
640 old
= ls_find_edge_by_source(ted
, attributes
);
642 /* Check if attributes are similar */
643 if (!ls_attributes_same(old
->attributes
, attributes
)) {
644 ls_attributes_del(old
->attributes
);
645 old
->attributes
= attributes
;
647 old
->status
= UPDATE
;
651 /* If not found, add new Edge from the attributes */
652 return ls_edge_add(ted
, attributes
);
655 int ls_edge_same(struct ls_edge
*e1
, struct ls_edge
*e2
)
657 if ((e1
&& !e2
) || (!e1
&& e2
))
663 if (e1
->key
!= e2
->key
)
666 if (e1
->attributes
== e2
->attributes
)
669 return ls_attributes_same(e1
->attributes
, e2
->attributes
);
672 void ls_edge_del(struct ls_ted
*ted
, struct ls_edge
*edge
)
677 /* Fist disconnect Edge from Vertices */
678 ls_disconnect_edge(edge
);
679 /* Then remove it from the Data Base */
680 edges_del(&ted
->edges
, edge
);
681 XFREE(MTYPE_LS_DB
, edge
);
684 void ls_edge_del_all(struct ls_ted
*ted
, struct ls_edge
*edge
)
689 /* Remove associated Link State Attributes */
690 ls_attributes_del(edge
->attributes
);
691 /* Then Edge itself */
692 ls_edge_del(ted
, edge
);
696 * Link State Subnet Management functions.
698 struct ls_subnet
*ls_subnet_add(struct ls_ted
*ted
,
699 struct ls_prefix
*ls_pref
)
701 struct ls_subnet
*new;
702 struct ls_vertex
*vertex
;
703 struct ls_node
*node
;
704 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
709 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_subnet
));
710 new->ls_pref
= ls_pref
;
711 new->key
= ls_pref
->pref
;
716 vertex
= ls_find_vertex_by_id(ted
, ls_pref
->adv
);
717 if (vertex
== NULL
) {
718 /* Create a new temporary Node & Vertex if not found */
719 node
= ls_node_new(ls_pref
->adv
, inaddr_any
, in6addr_any
);
720 vertex
= ls_vertex_add(ted
, node
);
722 /* And attach the subnet to the corresponding Vertex */
723 new->vertex
= vertex
;
724 listnode_add_sort_nodup(vertex
->prefixes
, new);
726 subnets_add(&ted
->subnets
, new);
731 struct ls_subnet
*ls_subnet_update(struct ls_ted
*ted
, struct ls_prefix
*pref
)
733 struct ls_subnet
*old
;
738 old
= ls_find_subnet(ted
, pref
->pref
);
740 if (!ls_prefix_same(old
->ls_pref
, pref
)) {
741 ls_prefix_del(old
->ls_pref
);
744 old
->status
= UPDATE
;
748 return ls_subnet_add(ted
, pref
);
751 int ls_subnet_same(struct ls_subnet
*s1
, struct ls_subnet
*s2
)
753 if ((s1
&& !s2
) || (!s1
&& s2
))
759 if (!prefix_same(&s1
->key
, &s2
->key
))
762 if (s1
->ls_pref
== s2
->ls_pref
)
765 return ls_prefix_same(s1
->ls_pref
, s2
->ls_pref
);
768 void ls_subnet_del(struct ls_ted
*ted
, struct ls_subnet
*subnet
)
773 /* First, disconnect Subnet from associated Vertex */
774 listnode_delete(subnet
->vertex
->prefixes
, subnet
);
775 /* Then delete Subnet */
776 subnets_del(&ted
->subnets
, subnet
);
777 XFREE(MTYPE_LS_DB
, subnet
);
780 void ls_subnet_del_all(struct ls_ted
*ted
, struct ls_subnet
*subnet
)
785 /* First, remove associated Link State Subnet */
786 ls_prefix_del(subnet
->ls_pref
);
787 /* Then, delete Subnet itself */
788 ls_subnet_del(ted
, subnet
);
791 struct ls_subnet
*ls_find_subnet(struct ls_ted
*ted
, const struct prefix prefix
)
793 struct ls_subnet subnet
= {};
796 return subnets_find(&ted
->subnets
, &subnet
);
800 * Link State TED management functions
802 struct ls_ted
*ls_ted_new(const uint32_t key
, const char *name
,
807 new = XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_ted
));
811 /* Set basic information for this ted */
813 new->as_number
= as_number
;
814 strlcpy(new->name
, name
, MAX_NAME_LENGTH
);
816 /* Initialize the various RB tree */
817 vertices_init(&new->vertices
);
818 edges_init(&new->edges
);
819 subnets_init(&new->subnets
);
824 void ls_ted_del(struct ls_ted
*ted
)
829 /* Check that TED is empty */
830 if (vertices_count(&ted
->vertices
) || edges_count(&ted
->edges
)
831 || subnets_count(&ted
->subnets
))
834 /* Release RB Tree */
835 vertices_fini(&ted
->vertices
);
836 edges_fini(&ted
->edges
);
837 subnets_fini(&ted
->subnets
);
839 XFREE(MTYPE_LS_DB
, ted
);
843 void ls_ted_del_all(struct ls_ted
*ted
)
845 struct ls_vertex
*vertex
;
846 struct ls_edge
*edge
;
847 struct ls_subnet
*subnet
;
852 /* First remove Vertices, Edges and Subnets and associated Link State */
853 frr_each (vertices
, &ted
->vertices
, vertex
)
854 ls_vertex_del_all(ted
, vertex
);
855 frr_each (edges
, &ted
->edges
, edge
)
856 ls_edge_del_all(ted
, edge
);
857 frr_each (subnets
, &ted
->subnets
, subnet
)
858 ls_subnet_del_all(ted
, subnet
);
860 /* then remove TED itself */
864 void ls_ted_clean(struct ls_ted
*ted
)
866 struct ls_vertex
*vertex
;
867 struct ls_edge
*edge
;
868 struct ls_subnet
*subnet
;
873 /* First, start with Vertices */
874 frr_each (vertices
, &ted
->vertices
, vertex
)
875 if (vertex
->status
== ORPHAN
)
876 ls_vertex_del_all(ted
, vertex
);
879 frr_each (edges
, &ted
->edges
, edge
)
880 if (edge
->status
== ORPHAN
)
881 ls_edge_del_all(ted
, edge
);
884 frr_each (subnets
, &ted
->subnets
, subnet
)
885 if (subnet
->status
== ORPHAN
)
886 ls_subnet_del_all(ted
, subnet
);
890 void ls_connect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
892 if (vertex
== NULL
|| edge
== NULL
)
896 listnode_add_sort_nodup(vertex
->outgoing_edges
, edge
);
897 edge
->source
= vertex
;
899 listnode_add_sort_nodup(vertex
->incoming_edges
, edge
);
900 edge
->destination
= vertex
;
904 void ls_disconnect(struct ls_vertex
*vertex
, struct ls_edge
*edge
, bool source
)
907 if (vertex
== NULL
|| edge
== NULL
)
911 listnode_delete(vertex
->outgoing_edges
, edge
);
914 listnode_delete(vertex
->incoming_edges
, edge
);
915 edge
->destination
= NULL
;
919 void ls_connect_vertices(struct ls_vertex
*src
, struct ls_vertex
*dst
,
920 struct ls_edge
*edge
)
926 edge
->destination
= dst
;
929 listnode_add_sort_nodup(src
->outgoing_edges
, edge
);
932 listnode_add_sort_nodup(dst
->incoming_edges
, edge
);
935 void ls_disconnect_edge(struct ls_edge
*edge
)
940 ls_disconnect(edge
->source
, edge
, true);
941 ls_disconnect(edge
->destination
, edge
, false);
943 /* Mark this Edge as ORPHAN for future cleanup */
944 edge
->status
= ORPHAN
;
948 * Link State Message management functions
951 int ls_register(struct zclient
*zclient
, bool server
)
956 rc
= zclient_register_opaque(zclient
, LINK_STATE_SYNC
);
958 rc
= zclient_register_opaque(zclient
, LINK_STATE_UPDATE
);
963 int ls_unregister(struct zclient
*zclient
, bool server
)
968 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_SYNC
);
970 rc
= zclient_unregister_opaque(zclient
, LINK_STATE_UPDATE
);
975 int ls_request_sync(struct zclient
*zclient
)
980 /* Check buffer size */
981 if (STREAM_SIZE(zclient
->obuf
)
982 < (ZEBRA_HEADER_SIZE
+ 3 * sizeof(uint32_t)))
988 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
990 /* Set type and flags */
991 stream_putl(s
, LINK_STATE_SYNC
);
992 stream_putw(s
, flags
);
993 /* Send destination client info */
994 stream_putc(s
, zclient
->redist_default
);
995 stream_putw(s
, zclient
->instance
);
996 stream_putl(s
, zclient
->session_id
);
998 /* Put length into the header at the start of the stream. */
999 stream_putw_at(s
, 0, stream_get_endp(s
));
1001 return zclient_send_message(zclient
);
1004 static struct ls_node
*ls_parse_node(struct stream
*s
)
1006 struct ls_node
*node
;
1009 node
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_node
));
1013 STREAM_GET(&node
->adv
, s
, sizeof(struct ls_node_id
));
1014 STREAM_GETW(s
, node
->flags
);
1015 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1016 STREAM_GETC(s
, len
);
1017 STREAM_GET(node
->name
, s
, len
);
1019 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1020 node
->router_id
.s_addr
= stream_get_ipv4(s
);
1021 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1022 STREAM_GET(&node
->router6_id
, s
, IPV6_MAX_BYTELEN
);
1023 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1024 STREAM_GETC(s
, node
->node_flag
);
1025 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1026 STREAM_GETC(s
, node
->type
);
1027 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1028 STREAM_GETL(s
, node
->as_number
);
1029 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1030 STREAM_GETL(s
, node
->srgb
.lower_bound
);
1031 STREAM_GETL(s
, node
->srgb
.range_size
);
1032 STREAM_GETC(s
, node
->srgb
.flag
);
1033 STREAM_GET(node
->algo
, s
, 2);
1035 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1036 STREAM_GETL(s
, node
->srlb
.lower_bound
);
1037 STREAM_GETL(s
, node
->srlb
.range_size
);
1039 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1040 STREAM_GETC(s
, node
->msd
);
1045 zlog_err("LS(%s): Could not parse Link State Node. Abort!", __func__
);
1046 XFREE(MTYPE_LS_DB
, node
);
1050 static struct ls_attributes
*ls_parse_attributes(struct stream
*s
)
1052 struct ls_attributes
*attr
;
1055 attr
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_attributes
));
1060 STREAM_GET(&attr
->adv
, s
, sizeof(struct ls_node_id
));
1061 STREAM_GETL(s
, attr
->flags
);
1062 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1063 STREAM_GETC(s
, len
);
1064 STREAM_GET(attr
->name
, s
, len
);
1066 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1067 STREAM_GETL(s
, attr
->metric
);
1068 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1069 STREAM_GETL(s
, attr
->standard
.te_metric
);
1070 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1071 STREAM_GETL(s
, attr
->standard
.admin_group
);
1072 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1073 attr
->standard
.local
.s_addr
= stream_get_ipv4(s
);
1074 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1075 attr
->standard
.remote
.s_addr
= stream_get_ipv4(s
);
1076 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1077 STREAM_GET(&attr
->standard
.local6
, s
, IPV6_MAX_BYTELEN
);
1078 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1079 STREAM_GET(&attr
->standard
.remote6
, s
, IPV6_MAX_BYTELEN
);
1080 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1081 STREAM_GETL(s
, attr
->standard
.local_id
);
1082 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1083 STREAM_GETL(s
, attr
->standard
.remote_id
);
1084 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1085 STREAM_GETF(s
, attr
->standard
.max_bw
);
1086 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1087 STREAM_GETF(s
, attr
->standard
.max_rsv_bw
);
1088 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1089 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1090 STREAM_GETF(s
, attr
->standard
.unrsv_bw
[len
]);
1091 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1092 STREAM_GETL(s
, attr
->standard
.remote_as
);
1093 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1094 attr
->standard
.remote_addr
.s_addr
= stream_get_ipv4(s
);
1095 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1096 STREAM_GET(&attr
->standard
.remote_addr6
, s
, IPV6_MAX_BYTELEN
);
1097 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1098 STREAM_GETL(s
, attr
->extended
.delay
);
1099 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1100 STREAM_GETL(s
, attr
->extended
.min_delay
);
1101 STREAM_GETL(s
, attr
->extended
.max_delay
);
1103 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1104 STREAM_GETL(s
, attr
->extended
.jitter
);
1105 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1106 STREAM_GETL(s
, attr
->extended
.pkt_loss
);
1107 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1108 STREAM_GETF(s
, attr
->extended
.ava_bw
);
1109 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1110 STREAM_GETF(s
, attr
->extended
.rsv_bw
);
1111 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1112 STREAM_GETF(s
, attr
->extended
.used_bw
);
1113 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1114 STREAM_GETL(s
, attr
->adj_sid
[0].sid
);
1115 STREAM_GETC(s
, attr
->adj_sid
[0].flags
);
1116 STREAM_GETC(s
, attr
->adj_sid
[0].weight
);
1117 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1118 STREAM_GET(attr
->adj_sid
[0].neighbor
.sysid
, s
,
1120 else if (attr
->adv
.origin
== OSPFv2
)
1121 attr
->adj_sid
[0].neighbor
.addr
.s_addr
=
1124 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1125 STREAM_GETL(s
, attr
->adj_sid
[1].sid
);
1126 STREAM_GETC(s
, attr
->adj_sid
[1].flags
);
1127 STREAM_GETC(s
, attr
->adj_sid
[1].weight
);
1128 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1129 STREAM_GET(attr
->adj_sid
[1].neighbor
.sysid
, s
,
1131 else if (attr
->adv
.origin
== OSPFv2
)
1132 attr
->adj_sid
[1].neighbor
.addr
.s_addr
=
1135 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1136 STREAM_GETC(s
, len
);
1137 attr
->srlgs
= XCALLOC(MTYPE_LS_DB
, len
*sizeof(uint32_t));
1138 attr
->srlg_len
= len
;
1139 for (len
= 0; len
< attr
->srlg_len
; len
++)
1140 STREAM_GETL(s
, attr
->srlgs
[len
]);
1146 zlog_err("LS(%s): Could not parse Link State Attributes. Abort!",
1148 /* Clean memory allocation */
1149 if (attr
->srlgs
!= NULL
)
1150 XFREE(MTYPE_LS_DB
, attr
->srlgs
);
1151 XFREE(MTYPE_LS_DB
, attr
);
1156 static struct ls_prefix
*ls_parse_prefix(struct stream
*s
)
1158 struct ls_prefix
*ls_pref
;
1161 ls_pref
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_prefix
));
1162 if (ls_pref
== NULL
)
1165 STREAM_GET(&ls_pref
->adv
, s
, sizeof(struct ls_node_id
));
1166 STREAM_GETW(s
, ls_pref
->flags
);
1167 STREAM_GETC(s
, ls_pref
->pref
.family
);
1168 STREAM_GETW(s
, ls_pref
->pref
.prefixlen
);
1169 len
= prefix_blen(&ls_pref
->pref
);
1170 STREAM_GET(&ls_pref
->pref
.u
.prefix
, s
, len
);
1171 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1172 STREAM_GETC(s
, ls_pref
->igp_flag
);
1173 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1174 STREAM_GETL(s
, ls_pref
->route_tag
);
1175 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1176 STREAM_GETQ(s
, ls_pref
->extended_tag
);
1177 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1178 STREAM_GETL(s
, ls_pref
->metric
);
1179 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1180 STREAM_GETL(s
, ls_pref
->sr
.sid
);
1181 STREAM_GETC(s
, ls_pref
->sr
.sid_flag
);
1182 STREAM_GETC(s
, ls_pref
->sr
.algo
);
1188 zlog_err("LS(%s): Could not parse Link State Prefix. Abort!", __func__
);
1189 XFREE(MTYPE_LS_DB
, ls_pref
);
1193 struct ls_message
*ls_parse_msg(struct stream
*s
)
1195 struct ls_message
*msg
;
1197 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1201 /* Read LS Message header */
1202 STREAM_GETC(s
, msg
->event
);
1203 STREAM_GETC(s
, msg
->type
);
1204 STREAM_GET(&msg
->remote_id
, s
, sizeof(struct ls_node_id
));
1206 /* Read Message Payload */
1207 switch (msg
->type
) {
1208 case LS_MSG_TYPE_NODE
:
1209 msg
->data
.node
= ls_parse_node(s
);
1211 case LS_MSG_TYPE_ATTRIBUTES
:
1212 msg
->data
.attr
= ls_parse_attributes(s
);
1214 case LS_MSG_TYPE_PREFIX
:
1215 msg
->data
.prefix
= ls_parse_prefix(s
);
1218 zlog_err("Unsupported Payload");
1219 goto stream_failure
;
1222 if (msg
->data
.node
== NULL
|| msg
->data
.attr
== NULL
1223 || msg
->data
.prefix
== NULL
)
1224 goto stream_failure
;
1229 zlog_err("LS(%s): Could not parse LS message. Abort!", __func__
);
1230 XFREE(MTYPE_LS_DB
, msg
);
1234 static int ls_format_node(struct stream
*s
, struct ls_node
*node
)
1238 /* Push Advertise node information first */
1239 stream_put(s
, &node
->adv
, sizeof(struct ls_node_id
));
1241 /* Push Flags & Origin then Node information if there are present */
1242 stream_putw(s
, node
->flags
);
1243 if (CHECK_FLAG(node
->flags
, LS_NODE_NAME
)) {
1244 len
= strlen(node
->name
);
1245 stream_putc(s
, len
+ 1);
1246 stream_put(s
, node
->name
, len
);
1247 stream_putc(s
, '\0');
1249 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID
))
1250 stream_put_ipv4(s
, node
->router_id
.s_addr
);
1251 if (CHECK_FLAG(node
->flags
, LS_NODE_ROUTER_ID6
))
1252 stream_put(s
, &node
->router6_id
, IPV6_MAX_BYTELEN
);
1253 if (CHECK_FLAG(node
->flags
, LS_NODE_FLAG
))
1254 stream_putc(s
, node
->node_flag
);
1255 if (CHECK_FLAG(node
->flags
, LS_NODE_TYPE
))
1256 stream_putc(s
, node
->type
);
1257 if (CHECK_FLAG(node
->flags
, LS_NODE_AS_NUMBER
))
1258 stream_putl(s
, node
->as_number
);
1259 if (CHECK_FLAG(node
->flags
, LS_NODE_SR
)) {
1260 stream_putl(s
, node
->srgb
.lower_bound
);
1261 stream_putl(s
, node
->srgb
.range_size
);
1262 stream_putc(s
, node
->srgb
.flag
);
1263 stream_put(s
, node
->algo
, 2);
1265 if (CHECK_FLAG(node
->flags
, LS_NODE_SRLB
)) {
1266 stream_putl(s
, node
->srlb
.lower_bound
);
1267 stream_putl(s
, node
->srlb
.range_size
);
1269 if (CHECK_FLAG(node
->flags
, LS_NODE_MSD
))
1270 stream_putc(s
, node
->msd
);
1275 static int ls_format_attributes(struct stream
*s
, struct ls_attributes
*attr
)
1279 /* Push Advertise node information first */
1280 stream_put(s
, &attr
->adv
, sizeof(struct ls_node_id
));
1282 /* Push Flags & Origin then LS attributes if there are present */
1283 stream_putl(s
, attr
->flags
);
1284 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
)) {
1285 len
= strlen(attr
->name
);
1286 stream_putc(s
, len
+ 1);
1287 stream_put(s
, attr
->name
, len
);
1288 stream_putc(s
, '\0');
1290 if (CHECK_FLAG(attr
->flags
, LS_ATTR_METRIC
))
1291 stream_putl(s
, attr
->metric
);
1292 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
1293 stream_putl(s
, attr
->standard
.te_metric
);
1294 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
1295 stream_putl(s
, attr
->standard
.admin_group
);
1296 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1297 stream_put_ipv4(s
, attr
->standard
.local
.s_addr
);
1298 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
1299 stream_put_ipv4(s
, attr
->standard
.remote
.s_addr
);
1300 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
1301 stream_put(s
, &attr
->standard
.local6
, IPV6_MAX_BYTELEN
);
1302 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
1303 stream_put(s
, &attr
->standard
.remote6
, IPV6_MAX_BYTELEN
);
1304 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
1305 stream_putl(s
, attr
->standard
.local_id
);
1306 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
1307 stream_putl(s
, attr
->standard
.remote_id
);
1308 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
1309 stream_putf(s
, attr
->standard
.max_bw
);
1310 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
1311 stream_putf(s
, attr
->standard
.max_rsv_bw
);
1312 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
))
1313 for (len
= 0; len
< MAX_CLASS_TYPE
; len
++)
1314 stream_putf(s
, attr
->standard
.unrsv_bw
[len
]);
1315 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
1316 stream_putl(s
, attr
->standard
.remote_as
);
1317 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
1318 stream_put_ipv4(s
, attr
->standard
.remote_addr
.s_addr
);
1319 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
1320 stream_put(s
, &attr
->standard
.remote_addr6
, IPV6_MAX_BYTELEN
);
1321 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
1322 stream_putl(s
, attr
->extended
.delay
);
1323 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
1324 stream_putl(s
, attr
->extended
.min_delay
);
1325 stream_putl(s
, attr
->extended
.max_delay
);
1327 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
1328 stream_putl(s
, attr
->extended
.jitter
);
1329 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
1330 stream_putl(s
, attr
->extended
.pkt_loss
);
1331 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
1332 stream_putf(s
, attr
->extended
.ava_bw
);
1333 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
1334 stream_putf(s
, attr
->extended
.rsv_bw
);
1335 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
1336 stream_putf(s
, attr
->extended
.used_bw
);
1337 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
1338 stream_putl(s
, attr
->adj_sid
[0].sid
);
1339 stream_putc(s
, attr
->adj_sid
[0].flags
);
1340 stream_putc(s
, attr
->adj_sid
[0].weight
);
1341 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1342 stream_put(s
, attr
->adj_sid
[0].neighbor
.sysid
,
1344 else if (attr
->adv
.origin
== OSPFv2
)
1346 attr
->adj_sid
[0].neighbor
.addr
.s_addr
);
1348 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
1349 stream_putl(s
, attr
->adj_sid
[1].sid
);
1350 stream_putc(s
, attr
->adj_sid
[1].flags
);
1351 stream_putc(s
, attr
->adj_sid
[1].weight
);
1352 if (attr
->adv
.origin
== ISIS_L1
|| attr
->adv
.origin
== ISIS_L2
)
1353 stream_put(s
, attr
->adj_sid
[1].neighbor
.sysid
,
1355 else if (attr
->adv
.origin
== OSPFv2
)
1357 attr
->adj_sid
[1].neighbor
.addr
.s_addr
);
1359 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
1360 stream_putc(s
, attr
->srlg_len
);
1361 for (len
= 0; len
< attr
->srlg_len
; len
++)
1362 stream_putl(s
, attr
->srlgs
[len
]);
1368 static int ls_format_prefix(struct stream
*s
, struct ls_prefix
*ls_pref
)
1372 /* Push Advertise node information first */
1373 stream_put(s
, &ls_pref
->adv
, sizeof(struct ls_node_id
));
1375 /* Push Flags, Origin & Prefix then information if there are present */
1376 stream_putw(s
, ls_pref
->flags
);
1377 stream_putc(s
, ls_pref
->pref
.family
);
1378 stream_putw(s
, ls_pref
->pref
.prefixlen
);
1379 len
= prefix_blen(&ls_pref
->pref
);
1380 stream_put(s
, &ls_pref
->pref
.u
.prefix
, len
);
1381 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_IGP_FLAG
))
1382 stream_putc(s
, ls_pref
->igp_flag
);
1383 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_ROUTE_TAG
))
1384 stream_putl(s
, ls_pref
->route_tag
);
1385 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_EXTENDED_TAG
))
1386 stream_putq(s
, ls_pref
->extended_tag
);
1387 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_METRIC
))
1388 stream_putl(s
, ls_pref
->metric
);
1389 if (CHECK_FLAG(ls_pref
->flags
, LS_PREF_SR
)) {
1390 stream_putl(s
, ls_pref
->sr
.sid
);
1391 stream_putc(s
, ls_pref
->sr
.sid_flag
);
1392 stream_putc(s
, ls_pref
->sr
.algo
);
1398 static int ls_format_msg(struct stream
*s
, struct ls_message
*msg
)
1401 /* Prepare Link State header */
1402 stream_putc(s
, msg
->event
);
1403 stream_putc(s
, msg
->type
);
1404 stream_put(s
, &msg
->remote_id
, sizeof(struct ls_node_id
));
1406 /* Add Message Payload */
1407 switch (msg
->type
) {
1408 case LS_MSG_TYPE_NODE
:
1409 return ls_format_node(s
, msg
->data
.node
);
1410 case LS_MSG_TYPE_ATTRIBUTES
:
1411 return ls_format_attributes(s
, msg
->data
.attr
);
1412 case LS_MSG_TYPE_PREFIX
:
1413 return ls_format_prefix(s
, msg
->data
.prefix
);
1415 zlog_warn("Unsupported Payload");
1422 int ls_send_msg(struct zclient
*zclient
, struct ls_message
*msg
,
1423 struct zapi_opaque_reg_info
*dst
)
1428 /* Check if we have a valid message */
1429 if (msg
->event
== LS_MSG_EVENT_UNDEF
)
1432 /* Check buffer size */
1433 if (STREAM_SIZE(zclient
->obuf
) <
1434 (ZEBRA_HEADER_SIZE
+ sizeof(uint32_t) + sizeof(msg
)))
1440 zclient_create_header(s
, ZEBRA_OPAQUE_MESSAGE
, VRF_DEFAULT
);
1442 /* Set sub-type, flags and destination for unicast message */
1443 stream_putl(s
, LINK_STATE_UPDATE
);
1445 SET_FLAG(flags
, ZAPI_OPAQUE_FLAG_UNICAST
);
1446 stream_putw(s
, flags
);
1447 /* Send destination client info */
1448 stream_putc(s
, dst
->proto
);
1449 stream_putw(s
, dst
->instance
);
1450 stream_putl(s
, dst
->session_id
);
1452 stream_putw(s
, flags
);
1455 /* Format Link State message */
1456 if (ls_format_msg(s
, msg
) < 0) {
1461 /* Put length into the header at the start of the stream. */
1462 stream_putw_at(s
, 0, stream_get_endp(s
));
1464 return zclient_send_message(zclient
);
1467 struct ls_message
*ls_vertex2msg(struct ls_message
*msg
,
1468 struct ls_vertex
*vertex
)
1470 /* Allocate space if needed */
1472 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1474 memset(msg
, 0, sizeof(*msg
));
1476 msg
->type
= LS_MSG_TYPE_NODE
;
1477 switch (vertex
->status
) {
1479 msg
->event
= LS_MSG_EVENT_ADD
;
1482 msg
->event
= LS_MSG_EVENT_UPDATE
;
1485 msg
->event
= LS_MSG_EVENT_DELETE
;
1488 msg
->event
= LS_MSG_EVENT_SYNC
;
1491 msg
->event
= LS_MSG_EVENT_UNDEF
;
1494 msg
->data
.node
= vertex
->node
;
1495 msg
->remote_id
.origin
= UNKNOWN
;
1500 struct ls_message
*ls_edge2msg(struct ls_message
*msg
, struct ls_edge
*edge
)
1502 /* Allocate space if needed */
1504 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1506 memset(msg
, 0, sizeof(*msg
));
1508 msg
->type
= LS_MSG_TYPE_ATTRIBUTES
;
1509 switch (edge
->status
) {
1511 msg
->event
= LS_MSG_EVENT_ADD
;
1514 msg
->event
= LS_MSG_EVENT_UPDATE
;
1517 msg
->event
= LS_MSG_EVENT_DELETE
;
1520 msg
->event
= LS_MSG_EVENT_SYNC
;
1523 msg
->event
= LS_MSG_EVENT_UNDEF
;
1526 msg
->data
.attr
= edge
->attributes
;
1527 if (edge
->destination
!= NULL
)
1528 msg
->remote_id
= edge
->destination
->node
->adv
;
1530 msg
->remote_id
.origin
= UNKNOWN
;
1535 struct ls_message
*ls_subnet2msg(struct ls_message
*msg
,
1536 struct ls_subnet
*subnet
)
1538 /* Allocate space if needed */
1540 msg
= XCALLOC(MTYPE_LS_DB
, sizeof(struct ls_message
));
1542 memset(msg
, 0, sizeof(*msg
));
1544 msg
->type
= LS_MSG_TYPE_PREFIX
;
1545 switch (subnet
->status
) {
1547 msg
->event
= LS_MSG_EVENT_ADD
;
1550 msg
->event
= LS_MSG_EVENT_UPDATE
;
1553 msg
->event
= LS_MSG_EVENT_DELETE
;
1556 msg
->event
= LS_MSG_EVENT_SYNC
;
1559 msg
->event
= LS_MSG_EVENT_UNDEF
;
1562 msg
->data
.prefix
= subnet
->ls_pref
;
1563 msg
->remote_id
.origin
= UNKNOWN
;
1568 struct ls_vertex
*ls_msg2vertex(struct ls_ted
*ted
, struct ls_message
*msg
,
1571 struct ls_node
*node
= (struct ls_node
*)msg
->data
.node
;
1572 struct ls_vertex
*vertex
= NULL
;
1574 switch (msg
->event
) {
1575 case LS_MSG_EVENT_SYNC
:
1576 vertex
= ls_vertex_add(ted
, node
);
1578 vertex
->status
= SYNC
;
1580 case LS_MSG_EVENT_ADD
:
1581 vertex
= ls_vertex_add(ted
, node
);
1583 vertex
->status
= NEW
;
1585 case LS_MSG_EVENT_UPDATE
:
1586 vertex
= ls_vertex_update(ted
, node
);
1588 vertex
->status
= UPDATE
;
1590 case LS_MSG_EVENT_DELETE
:
1591 vertex
= ls_find_vertex_by_id(ted
, node
->adv
);
1594 ls_vertex_del_all(ted
, vertex
);
1596 vertex
->status
= DELETE
;
1607 struct ls_edge
*ls_msg2edge(struct ls_ted
*ted
, struct ls_message
*msg
,
1610 struct ls_attributes
*attr
= (struct ls_attributes
*)msg
->data
.attr
;
1611 struct ls_edge
*edge
= NULL
;
1613 switch (msg
->event
) {
1614 case LS_MSG_EVENT_SYNC
:
1615 edge
= ls_edge_add(ted
, attr
);
1617 edge
->status
= SYNC
;
1619 case LS_MSG_EVENT_ADD
:
1620 edge
= ls_edge_add(ted
, attr
);
1624 case LS_MSG_EVENT_UPDATE
:
1625 edge
= ls_edge_update(ted
, attr
);
1627 edge
->status
= UPDATE
;
1629 case LS_MSG_EVENT_DELETE
:
1630 edge
= ls_find_edge_by_source(ted
, attr
);
1633 ls_edge_del_all(ted
, edge
);
1635 edge
->status
= DELETE
;
1646 struct ls_subnet
*ls_msg2subnet(struct ls_ted
*ted
, struct ls_message
*msg
,
1649 struct ls_prefix
*pref
= (struct ls_prefix
*)msg
->data
.prefix
;
1650 struct ls_subnet
*subnet
= NULL
;
1652 switch (msg
->event
) {
1653 case LS_MSG_EVENT_SYNC
:
1654 subnet
= ls_subnet_add(ted
, pref
);
1656 subnet
->status
= SYNC
;
1658 case LS_MSG_EVENT_ADD
:
1659 subnet
= ls_subnet_add(ted
, pref
);
1661 subnet
->status
= NEW
;
1663 case LS_MSG_EVENT_UPDATE
:
1664 subnet
= ls_subnet_update(ted
, pref
);
1666 subnet
->status
= UPDATE
;
1668 case LS_MSG_EVENT_DELETE
:
1669 subnet
= ls_find_subnet(ted
, pref
->pref
);
1672 ls_subnet_del_all(ted
, subnet
);
1674 subnet
->status
= DELETE
;
1685 struct ls_element
*ls_msg2ted(struct ls_ted
*ted
, struct ls_message
*msg
,
1688 struct ls_element
*lse
= NULL
;
1690 switch (msg
->type
) {
1691 case LS_MSG_TYPE_NODE
:
1692 lse
= (struct ls_element
*)ls_msg2vertex(ted
, msg
, delete);
1694 case LS_MSG_TYPE_ATTRIBUTES
:
1695 lse
= (struct ls_element
*)ls_msg2edge(ted
, msg
, delete);
1697 case LS_MSG_TYPE_PREFIX
:
1698 lse
= (struct ls_element
*)ls_msg2subnet(ted
, msg
, delete);
1708 struct ls_element
*ls_stream2ted(struct ls_ted
*ted
, struct stream
*s
,
1711 struct ls_message
*msg
;
1712 struct ls_element
*lse
= NULL
;
1714 msg
= ls_parse_msg(s
);
1716 lse
= ls_msg2ted(ted
, msg
, delete);
1723 void ls_delete_msg(struct ls_message
*msg
)
1728 XFREE(MTYPE_LS_DB
, msg
);
1731 int ls_sync_ted(struct ls_ted
*ted
, struct zclient
*zclient
,
1732 struct zapi_opaque_reg_info
*dst
)
1734 struct ls_vertex
*vertex
;
1735 struct ls_edge
*edge
;
1736 struct ls_subnet
*subnet
;
1737 struct ls_message msg
;
1739 /* Loop TED, start sending Node, then Attributes and finally Prefix */
1740 frr_each(vertices
, &ted
->vertices
, vertex
) {
1741 ls_vertex2msg(&msg
, vertex
);
1742 ls_send_msg(zclient
, &msg
, dst
);
1744 frr_each(edges
, &ted
->edges
, edge
) {
1745 ls_edge2msg(&msg
, edge
);
1746 ls_send_msg(zclient
, &msg
, dst
);
1748 frr_each(subnets
, &ted
->subnets
, subnet
) {
1749 ls_subnet2msg(&msg
, subnet
);
1750 ls_send_msg(zclient
, &msg
, dst
);
1756 * Link State Show functions
1758 static const char *const origin2txt
[] = {
1767 static const char *const type2txt
[] = {
1776 static const char *const status2txt
[] = {
1785 static const char *ls_node_id_to_text(struct ls_node_id lnid
, char *str
,
1788 if (lnid
.origin
== ISIS_L1
|| lnid
.origin
== ISIS_L2
) {
1791 id
= lnid
.id
.iso
.sys_id
;
1792 snprintfrr(str
, size
, "%02x%02x.%02x%02x.%02x%02x", id
[0],
1793 id
[1], id
[2], id
[3], id
[4], id
[5]);
1795 snprintfrr(str
, size
, "%pI4", &lnid
.id
.ip
.addr
);
1800 static void ls_show_vertex_vty(struct ls_vertex
*vertex
, struct vty
*vty
,
1803 struct listnode
*node
;
1804 struct ls_node
*lsn
;
1805 struct ls_edge
*edge
;
1806 struct ls_subnet
*subnet
;
1816 sbuf_init(&sbuf
, NULL
, 0);
1818 sbuf_push(&sbuf
, 2, "Vertex (%" PRIu64
"): %s", vertex
->key
, lsn
->name
);
1819 sbuf_push(&sbuf
, 0, "\tRouter Id: %pI4", &lsn
->router_id
);
1820 sbuf_push(&sbuf
, 0, "\tOrigin: %s", origin2txt
[lsn
->adv
.origin
]);
1821 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[vertex
->status
]);
1825 "\t%d Outgoing Edges, %d Incoming Edges, %d Subnets\n",
1826 listcount(vertex
->outgoing_edges
),
1827 listcount(vertex
->incoming_edges
),
1828 listcount(vertex
->prefixes
));
1832 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
1833 sbuf_push(&sbuf
, 4, "Type: %s\n", type2txt
[lsn
->type
]);
1834 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
1835 sbuf_push(&sbuf
, 4, "AS number: %u\n", lsn
->as_number
);
1836 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
1837 sbuf_push(&sbuf
, 4, "Segment Routing Capabilities:\n");
1838 upper
= lsn
->srgb
.lower_bound
+ lsn
->srgb
.range_size
- 1;
1839 sbuf_push(&sbuf
, 8, "SRGB: [%d/%d]", lsn
->srgb
.lower_bound
,
1841 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
1842 upper
= lsn
->srlb
.lower_bound
+ lsn
->srlb
.range_size
1844 sbuf_push(&sbuf
, 0, "\tSRLB: [%d/%d]",
1845 lsn
->srlb
.lower_bound
, upper
);
1847 sbuf_push(&sbuf
, 0, "\tAlgo: ");
1848 for (int i
= 0; i
< 2; i
++) {
1849 if (lsn
->algo
[i
] == 255)
1853 lsn
->algo
[i
] == 0 ? "SPF " : "S-SPF ");
1855 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
1856 sbuf_push(&sbuf
, 0, "\tMSD: %d", lsn
->msd
);
1857 sbuf_push(&sbuf
, 0, "\n");
1860 sbuf_push(&sbuf
, 4, "Outgoing Edges: %d\n",
1861 listcount(vertex
->outgoing_edges
));
1862 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, node
, edge
)) {
1863 if (edge
->destination
) {
1864 lsn
= edge
->destination
->node
;
1865 sbuf_push(&sbuf
, 6, "To:\t%s(%pI4)", lsn
->name
,
1868 sbuf_push(&sbuf
, 6, "To:\t- (0.0.0.0)");
1870 sbuf_push(&sbuf
, 0, "\tLocal: %pI4\tRemote: %pI4\n",
1871 &edge
->attributes
->standard
.local
,
1872 &edge
->attributes
->standard
.remote
);
1875 sbuf_push(&sbuf
, 4, "Incoming Edges: %d\n",
1876 listcount(vertex
->incoming_edges
));
1877 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, node
, edge
)) {
1879 lsn
= edge
->source
->node
;
1880 sbuf_push(&sbuf
, 6, "From:\t%s(%pI4)", lsn
->name
,
1883 sbuf_push(&sbuf
, 6, "From:\t- (0.0.0.0)");
1885 sbuf_push(&sbuf
, 0, "\tRemote: %pI4\tLocal: %pI4\n",
1886 &edge
->attributes
->standard
.local
,
1887 &edge
->attributes
->standard
.remote
);
1890 sbuf_push(&sbuf
, 4, "Subnets: %d\n", listcount(vertex
->prefixes
));
1891 for (ALL_LIST_ELEMENTS_RO(vertex
->prefixes
, node
, subnet
))
1892 sbuf_push(&sbuf
, 6, "Prefix:\t%pFX\n", &subnet
->key
);
1895 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
1899 static void ls_show_vertex_json(struct ls_vertex
*vertex
,
1900 struct json_object
*json
)
1902 struct ls_node
*lsn
;
1903 json_object
*jsr
, *jalgo
, *jobj
;
1904 char buf
[INET6_BUFSIZ
];
1912 json_object_int_add(json
, "vertex-id", vertex
->key
);
1913 json_object_string_add(json
, "status", status2txt
[vertex
->status
]);
1914 json_object_string_add(json
, "origin", origin2txt
[lsn
->adv
.origin
]);
1915 if (CHECK_FLAG(lsn
->flags
, LS_NODE_NAME
))
1916 json_object_string_add(json
, "name", lsn
->name
);
1917 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID
)) {
1918 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &lsn
->router_id
);
1919 json_object_string_add(json
, "router-id", buf
);
1921 if (CHECK_FLAG(lsn
->flags
, LS_NODE_ROUTER_ID6
)) {
1922 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &lsn
->router6_id
);
1923 json_object_string_add(json
, "router-id-v6", buf
);
1925 if (CHECK_FLAG(lsn
->flags
, LS_NODE_TYPE
))
1926 json_object_string_add(json
, "vertex-type",
1927 type2txt
[lsn
->type
]);
1928 if (CHECK_FLAG(lsn
->flags
, LS_NODE_AS_NUMBER
))
1929 json_object_int_add(json
, "asn", lsn
->as_number
);
1930 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SR
)) {
1931 jsr
= json_object_new_object();
1932 json_object_object_add(json
, "segment-routing", jsr
);
1933 json_object_int_add(jsr
, "srgb-size", lsn
->srgb
.range_size
);
1934 json_object_int_add(jsr
, "srgb-lower", lsn
->srgb
.lower_bound
);
1935 jalgo
= json_object_new_array();
1936 json_object_object_add(jsr
, "algorithms", jalgo
);
1937 for (int i
= 0; i
< 2; i
++) {
1938 if (lsn
->algo
[i
] == 255)
1940 jobj
= json_object_new_object();
1942 snprintfrr(buf
, 2, "%u", i
);
1943 json_object_string_add(
1944 jobj
, buf
, lsn
->algo
[i
] == 0 ? "SPF" : "S-SPF");
1945 json_object_array_add(jalgo
, jobj
);
1947 if (CHECK_FLAG(lsn
->flags
, LS_NODE_SRLB
)) {
1948 json_object_int_add(jsr
, "srlb-size",
1949 lsn
->srlb
.range_size
);
1950 json_object_int_add(jsr
, "srlb-lower",
1951 lsn
->srlb
.lower_bound
);
1953 if (CHECK_FLAG(lsn
->flags
, LS_NODE_MSD
))
1954 json_object_int_add(jsr
, "msd", lsn
->msd
);
1958 void ls_show_vertex(struct ls_vertex
*vertex
, struct vty
*vty
,
1959 struct json_object
*json
, bool verbose
)
1962 ls_show_vertex_json(vertex
, json
);
1964 ls_show_vertex_vty(vertex
, vty
, verbose
);
1967 void ls_show_vertices(struct ls_ted
*ted
, struct vty
*vty
,
1968 struct json_object
*json
, bool verbose
)
1970 struct ls_vertex
*vertex
;
1971 json_object
*jnodes
, *jnode
;
1974 jnodes
= json_object_new_array();
1975 json_object_object_add(json
, "vertices", jnodes
);
1976 frr_each (vertices
, &ted
->vertices
, vertex
) {
1977 jnode
= json_object_new_object();
1978 ls_show_vertex(vertex
, NULL
, jnode
, verbose
);
1979 json_object_array_add(jnodes
, jnode
);
1982 frr_each (vertices
, &ted
->vertices
, vertex
)
1983 ls_show_vertex(vertex
, vty
, NULL
, verbose
);
1987 static void ls_show_edge_vty(struct ls_edge
*edge
, struct vty
*vty
,
1990 struct ls_attributes
*attr
;
1992 char buf
[INET6_BUFSIZ
];
1994 attr
= edge
->attributes
;
1995 sbuf_init(&sbuf
, NULL
, 0);
1997 sbuf_push(&sbuf
, 2, "Edge (%" PRIu64
"): ", edge
->key
);
1998 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
1999 sbuf_push(&sbuf
, 0, "%pI4", &attr
->standard
.local
);
2000 else if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
2001 sbuf_push(&sbuf
, 0, "%pI6", &attr
->standard
.local6
);
2003 sbuf_push(&sbuf
, 0, "%u/%u", attr
->standard
.local_id
,
2004 attr
->standard
.remote_id
);
2005 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
2006 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
2007 sbuf_push(&sbuf
, 0, "\tMetric: %u", attr
->metric
);
2008 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[edge
->status
]);
2013 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[attr
->adv
.origin
]);
2014 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2015 sbuf_push(&sbuf
, 4, "Name: %s\n", attr
->name
);
2016 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2017 sbuf_push(&sbuf
, 4, "TE Metric: %u\n",
2018 attr
->standard
.te_metric
);
2019 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2020 sbuf_push(&sbuf
, 4, "Admin Group: 0x%x\n",
2021 attr
->standard
.admin_group
);
2022 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
))
2023 sbuf_push(&sbuf
, 4, "Local IPv4 address: %pI4\n",
2024 &attr
->standard
.local
);
2025 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
))
2026 sbuf_push(&sbuf
, 4, "Remote IPv4 address: %pI4\n",
2027 &attr
->standard
.remote
);
2028 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
))
2029 sbuf_push(&sbuf
, 4, "Local IPv6 address: %pI6\n",
2030 &attr
->standard
.local6
);
2031 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
))
2032 sbuf_push(&sbuf
, 4, "Remote IPv6 address: %pI6\n",
2033 &attr
->standard
.remote6
);
2034 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2035 sbuf_push(&sbuf
, 4, "Local Identifier: %u\n",
2036 attr
->standard
.local_id
);
2037 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2038 sbuf_push(&sbuf
, 4, "Remote Identifier: %u\n",
2039 attr
->standard
.remote_id
);
2040 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2041 sbuf_push(&sbuf
, 4, "Maximum Bandwidth: %g (Bytes/s)\n",
2042 attr
->standard
.max_bw
);
2043 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2045 "Maximum Reservable Bandwidth: %g (Bytes/s)\n",
2046 attr
->standard
.max_rsv_bw
);
2047 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2048 sbuf_push(&sbuf
, 4, "Unreserved Bandwidth per Class Type\n");
2049 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
+= 2)
2051 "[%d]: %g (Bytes/sec)\t[%d]: %g (Bytes/s)\n",
2052 i
, attr
->standard
.unrsv_bw
[i
], i
+ 1,
2053 attr
->standard
.unrsv_bw
[i
+ 1]);
2055 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2056 sbuf_push(&sbuf
, 4, "Remote AS: %u\n",
2057 attr
->standard
.remote_as
);
2058 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
))
2059 sbuf_push(&sbuf
, 4, "Remote ASBR IPv4 address: %pI4\n",
2060 &attr
->standard
.remote_addr
);
2061 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
))
2062 sbuf_push(&sbuf
, 4, "Remote ASBR IPv6 address: %pI6\n",
2063 &attr
->standard
.remote_addr6
);
2064 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2065 sbuf_push(&sbuf
, 4, "Average Link Delay: %d (micro-sec)\n",
2066 attr
->extended
.delay
);
2067 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
))
2068 sbuf_push(&sbuf
, 4, "Min/Max Link Delay: %d/%d (micro-sec)\n",
2069 attr
->extended
.min_delay
, attr
->extended
.max_delay
);
2070 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2071 sbuf_push(&sbuf
, 4, "Delay Variation: %d (micro-sec)\n",
2072 attr
->extended
.jitter
);
2073 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2074 sbuf_push(&sbuf
, 4, "Link Loss: %g (%%)\n",
2075 (float)(attr
->extended
.pkt_loss
* LOSS_PRECISION
));
2076 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2077 sbuf_push(&sbuf
, 4, "Available Bandwidth: %g (Bytes/s)\n",
2078 attr
->extended
.ava_bw
);
2079 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2080 sbuf_push(&sbuf
, 4, "Residual Bandwidth: %g (Bytes/s)\n",
2081 attr
->extended
.rsv_bw
);
2082 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2083 sbuf_push(&sbuf
, 4, "Utilized Bandwidth: %g (Bytes/s)\n",
2084 attr
->extended
.used_bw
);
2085 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2086 sbuf_push(&sbuf
, 4, "Adjacency-SID: %u", attr
->adj_sid
[0].sid
);
2087 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2088 attr
->adj_sid
[0].flags
, attr
->adj_sid
[0].weight
);
2090 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2091 sbuf_push(&sbuf
, 4, "Bck. Adjacency-SID: %u",
2092 attr
->adj_sid
[1].sid
);
2093 sbuf_push(&sbuf
, 0, "\tFlags: 0x%x\tWeight: 0x%x\n",
2094 attr
->adj_sid
[1].flags
, attr
->adj_sid
[1].weight
);
2096 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2097 sbuf_push(&sbuf
, 4, "SRLGs: %d", attr
->srlg_len
);
2098 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2100 sbuf_push(&sbuf
, 8, "\n%u", attr
->srlgs
[i
]);
2102 sbuf_push(&sbuf
, 8, ", %u", attr
->srlgs
[i
]);
2104 sbuf_push(&sbuf
, 0, "\n");
2108 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2112 static void ls_show_edge_json(struct ls_edge
*edge
, struct json_object
*json
)
2114 struct ls_attributes
*attr
;
2115 struct json_object
*jte
, *jbw
, *jobj
, *jsr
= NULL
, *jsrlg
;
2116 char buf
[INET6_BUFSIZ
];
2118 attr
= edge
->attributes
;
2120 json_object_int_add(json
, "edge-id", edge
->key
);
2121 json_object_string_add(json
, "status", status2txt
[edge
->status
]);
2122 json_object_string_add(json
, "origin", origin2txt
[attr
->adv
.origin
]);
2123 ls_node_id_to_text(attr
->adv
, buf
, INET6_BUFSIZ
);
2124 json_object_string_add(json
, "advertised-router", buf
);
2126 json_object_int_add(json
, "local-vertex-id", edge
->source
->key
);
2127 if (edge
->destination
)
2128 json_object_int_add(json
, "remote-vertex-id",
2129 edge
->destination
->key
);
2130 json_object_int_add(json
, "metric", attr
->metric
);
2131 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NAME
))
2132 json_object_string_add(json
, "name", attr
->name
);
2133 jte
= json_object_new_object();
2134 json_object_object_add(json
, "edge-attributes", jte
);
2135 if (CHECK_FLAG(attr
->flags
, LS_ATTR_TE_METRIC
))
2136 json_object_int_add(jte
, "te-metric", attr
->standard
.te_metric
);
2137 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADM_GRP
))
2138 json_object_int_add(jte
, "admin-group",
2139 attr
->standard
.admin_group
);
2140 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR
)) {
2141 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.local
);
2142 json_object_string_add(jte
, "local-address", buf
);
2144 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR
)) {
2145 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4", &attr
->standard
.remote
);
2146 json_object_string_add(jte
, "remote-address", buf
);
2148 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ADDR6
)) {
2149 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.local6
);
2150 json_object_string_add(jte
, "local-address-v6", buf
);
2152 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ADDR6
)) {
2153 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6", &attr
->standard
.remote6
);
2154 json_object_string_add(jte
, "remote-address-v6", buf
);
2156 if (CHECK_FLAG(attr
->flags
, LS_ATTR_LOCAL_ID
))
2157 json_object_int_add(jte
, "local-identifier",
2158 attr
->standard
.local_id
);
2159 if (CHECK_FLAG(attr
->flags
, LS_ATTR_NEIGH_ID
))
2160 json_object_int_add(jte
, "remote-identifier",
2161 attr
->standard
.remote_id
);
2162 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_BW
))
2163 json_object_double_add(jte
, "max-link-bandwidth",
2164 attr
->standard
.max_bw
);
2165 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MAX_RSV_BW
))
2166 json_object_double_add(jte
, "max-resv-link-bandwidth",
2167 attr
->standard
.max_rsv_bw
);
2168 if (CHECK_FLAG(attr
->flags
, LS_ATTR_UNRSV_BW
)) {
2169 jbw
= json_object_new_array();
2170 json_object_object_add(jte
, "unreserved-bandwidth", jbw
);
2171 for (int i
= 0; i
< MAX_CLASS_TYPE
; i
++) {
2172 jobj
= json_object_new_object();
2173 snprintfrr(buf
, 13, "class-type-%u", i
);
2174 json_object_double_add(jobj
, buf
,
2175 attr
->standard
.unrsv_bw
[i
]);
2176 json_object_array_add(jbw
, jobj
);
2179 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_AS
))
2180 json_object_int_add(jte
, "remote-asn",
2181 attr
->standard
.remote_as
);
2182 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR
)) {
2183 snprintfrr(buf
, INET6_BUFSIZ
, "%pI4",
2184 &attr
->standard
.remote_addr
);
2185 json_object_string_add(jte
, "remote-as-address", buf
);
2187 if (CHECK_FLAG(attr
->flags
, LS_ATTR_REMOTE_ADDR6
)) {
2188 snprintfrr(buf
, INET6_BUFSIZ
, "%pI6",
2189 &attr
->standard
.remote_addr6
);
2190 json_object_string_add(jte
, "remote-as-address-v6", buf
);
2192 if (CHECK_FLAG(attr
->flags
, LS_ATTR_DELAY
))
2193 json_object_int_add(jte
, "delay", attr
->extended
.delay
);
2194 if (CHECK_FLAG(attr
->flags
, LS_ATTR_MIN_MAX_DELAY
)) {
2195 json_object_int_add(jte
, "min-delay", attr
->extended
.min_delay
);
2196 json_object_int_add(jte
, "max-delay", attr
->extended
.max_delay
);
2198 if (CHECK_FLAG(attr
->flags
, LS_ATTR_JITTER
))
2199 json_object_int_add(jte
, "jitter", attr
->extended
.jitter
);
2200 if (CHECK_FLAG(attr
->flags
, LS_ATTR_PACKET_LOSS
))
2201 json_object_double_add(
2202 jte
, "loss", attr
->extended
.pkt_loss
* LOSS_PRECISION
);
2203 if (CHECK_FLAG(attr
->flags
, LS_ATTR_AVA_BW
))
2204 json_object_double_add(jte
, "available-bandwidth",
2205 attr
->extended
.ava_bw
);
2206 if (CHECK_FLAG(attr
->flags
, LS_ATTR_RSV_BW
))
2207 json_object_double_add(jte
, "residual-bandwidth",
2208 attr
->extended
.rsv_bw
);
2209 if (CHECK_FLAG(attr
->flags
, LS_ATTR_USE_BW
))
2210 json_object_double_add(jte
, "utilized-bandwidth",
2211 attr
->extended
.used_bw
);
2212 if (CHECK_FLAG(attr
->flags
, LS_ATTR_SRLG
)) {
2213 jsrlg
= json_object_new_array();
2214 json_object_object_add(jte
, "srlgs", jsrlg
);
2215 for (int i
= 1; i
< attr
->srlg_len
; i
++) {
2216 jobj
= json_object_new_object();
2217 json_object_int_add(jobj
, "srlg", attr
->srlgs
[i
]);
2218 json_object_array_add(jsrlg
, jobj
);
2221 if (CHECK_FLAG(attr
->flags
, LS_ATTR_ADJ_SID
)) {
2222 jsr
= json_object_new_array();
2223 json_object_object_add(json
, "segment-routing", jsr
);
2224 jobj
= json_object_new_object();
2225 json_object_int_add(jobj
, "adj-sid", attr
->adj_sid
[0].sid
);
2226 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[0].flags
);
2227 json_object_string_add(jobj
, "flags", buf
);
2228 json_object_int_add(jobj
, "weight", attr
->adj_sid
[0].weight
);
2229 json_object_array_add(jsr
, jobj
);
2231 if (CHECK_FLAG(attr
->flags
, LS_ATTR_BCK_ADJ_SID
)) {
2233 jsr
= json_object_new_array();
2234 json_object_object_add(json
, "segment-routing", jsr
);
2236 jobj
= json_object_new_object();
2237 json_object_int_add(jobj
, "adj-sid", attr
->adj_sid
[1].sid
);
2238 snprintfrr(buf
, 6, "0x%x", attr
->adj_sid
[1].flags
);
2239 json_object_string_add(jobj
, "flags", buf
);
2240 json_object_int_add(jobj
, "weight", attr
->adj_sid
[1].weight
);
2241 json_object_array_add(jsr
, jobj
);
2245 void ls_show_edge(struct ls_edge
*edge
, struct vty
*vty
,
2246 struct json_object
*json
, bool verbose
)
2253 ls_show_edge_json(edge
, json
);
2255 ls_show_edge_vty(edge
, vty
, verbose
);
2258 void ls_show_edges(struct ls_ted
*ted
, struct vty
*vty
,
2259 struct json_object
*json
, bool verbose
)
2261 struct ls_edge
*edge
;
2262 json_object
*jedges
, *jedge
;
2265 jedges
= json_object_new_array();
2266 json_object_object_add(json
, "edges", jedges
);
2267 frr_each (edges
, &ted
->edges
, edge
) {
2268 jedge
= json_object_new_object();
2269 ls_show_edge(edge
, NULL
, jedge
, verbose
);
2270 json_object_array_add(jedges
, jedge
);
2273 frr_each (edges
, &ted
->edges
, edge
)
2274 ls_show_edge(edge
, vty
, NULL
, verbose
);
2278 static void ls_show_subnet_vty(struct ls_subnet
*subnet
, struct vty
*vty
,
2281 struct ls_prefix
*pref
;
2283 char buf
[INET6_BUFSIZ
];
2285 pref
= subnet
->ls_pref
;
2286 sbuf_init(&sbuf
, NULL
, 0);
2288 sbuf_push(&sbuf
, 2, "Subnet: %pFX", &subnet
->key
);
2289 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2290 sbuf_push(&sbuf
, 0, "\tAdv. Vertex: %s", buf
);
2291 sbuf_push(&sbuf
, 0, "\tMetric: %d", pref
->metric
);
2292 sbuf_push(&sbuf
, 0, "\tStatus: %s\n", status2txt
[subnet
->status
]);
2297 sbuf_push(&sbuf
, 4, "Origin: %s\n", origin2txt
[pref
->adv
.origin
]);
2298 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
))
2299 sbuf_push(&sbuf
, 4, "Flags: %d\n", pref
->igp_flag
);
2301 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2302 sbuf_push(&sbuf
, 4, "Tag: %d\n", pref
->route_tag
);
2304 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2305 sbuf_push(&sbuf
, 4, "Extended Tag: %" PRIu64
"\n",
2306 pref
->extended_tag
);
2308 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
))
2309 sbuf_push(&sbuf
, 4, "SID: %d\tAlgorithm: %d\tFlags: 0x%x\n",
2310 pref
->sr
.sid
, pref
->sr
.algo
, pref
->sr
.sid_flag
);
2313 vty_out(vty
, "%s\n", sbuf_buf(&sbuf
));
2317 static void ls_show_subnet_json(struct ls_subnet
*subnet
,
2318 struct json_object
*json
)
2320 struct ls_prefix
*pref
;
2322 char buf
[INET6_BUFSIZ
];
2324 pref
= subnet
->ls_pref
;
2326 snprintfrr(buf
, INET6_BUFSIZ
, "%pFX", &subnet
->key
);
2327 json_object_string_add(json
, "subnet-id", buf
);
2328 json_object_string_add(json
, "status", status2txt
[subnet
->status
]);
2329 json_object_string_add(json
, "origin", origin2txt
[pref
->adv
.origin
]);
2330 ls_node_id_to_text(pref
->adv
, buf
, INET6_BUFSIZ
);
2331 json_object_string_add(json
, "advertised-router", buf
);
2333 json_object_int_add(json
, "vertex-id", subnet
->vertex
->key
);
2334 json_object_int_add(json
, "metric", pref
->metric
);
2335 if (CHECK_FLAG(pref
->flags
, LS_PREF_IGP_FLAG
)) {
2336 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->igp_flag
);
2337 json_object_string_add(json
, "flags", buf
);
2339 if (CHECK_FLAG(pref
->flags
, LS_PREF_ROUTE_TAG
))
2340 json_object_int_add(json
, "tag", pref
->route_tag
);
2341 if (CHECK_FLAG(pref
->flags
, LS_PREF_EXTENDED_TAG
))
2342 json_object_int_add(json
, "extended-tag", pref
->extended_tag
);
2343 if (CHECK_FLAG(pref
->flags
, LS_PREF_SR
)) {
2344 jsr
= json_object_new_object();
2345 json_object_object_add(json
, "segment-routing", jsr
);
2346 json_object_int_add(jsr
, "pref-sid", pref
->sr
.sid
);
2347 json_object_int_add(jsr
, "algo", pref
->sr
.algo
);
2348 snprintfrr(buf
, INET6_BUFSIZ
, "0x%x", pref
->sr
.sid_flag
);
2349 json_object_string_add(jsr
, "flags", buf
);
2353 void ls_show_subnet(struct ls_subnet
*subnet
, struct vty
*vty
,
2354 struct json_object
*json
, bool verbose
)
2361 ls_show_subnet_json(subnet
, json
);
2363 ls_show_subnet_vty(subnet
, vty
, verbose
);
2366 void ls_show_subnets(struct ls_ted
*ted
, struct vty
*vty
,
2367 struct json_object
*json
, bool verbose
)
2369 struct ls_subnet
*subnet
;
2370 json_object
*jsubs
, *jsub
;
2373 jsubs
= json_object_new_array();
2374 json_object_object_add(json
, "subnets", jsubs
);
2375 frr_each (subnets
, &ted
->subnets
, subnet
) {
2376 jsub
= json_object_new_object();
2377 ls_show_subnet(subnet
, NULL
, jsub
, verbose
);
2378 json_object_array_add(jsubs
, jsub
);
2381 frr_each (subnets
, &ted
->subnets
, subnet
)
2382 ls_show_subnet(subnet
, vty
, NULL
, verbose
);
2386 void ls_show_ted(struct ls_ted
*ted
, struct vty
*vty
, struct json_object
*json
,
2392 jted
= json_object_new_object();
2393 json_object_object_add(json
, "ted", jted
);
2394 json_object_string_add(jted
, "name", ted
->name
);
2395 json_object_int_add(jted
, "key", ted
->key
);
2396 json_object_int_add(jted
, "verticesCount",
2397 vertices_count(&ted
->vertices
));
2398 json_object_int_add(jted
, "edgesCount",
2399 edges_count(&ted
->edges
));
2400 json_object_int_add(jted
, "subnetsCount",
2401 subnets_count(&ted
->subnets
));
2402 ls_show_vertices(ted
, NULL
, jted
, verbose
);
2403 ls_show_edges(ted
, NULL
, jted
, verbose
);
2404 ls_show_subnets(ted
, NULL
, jted
, verbose
);
2410 "\n\tTraffic Engineering Database: %s (key: %d)\n\n",
2411 ted
->name
, ted
->key
);
2412 ls_show_vertices(ted
, vty
, NULL
, verbose
);
2413 ls_show_edges(ted
, vty
, NULL
, verbose
);
2414 ls_show_subnets(ted
, vty
, NULL
, verbose
);
2416 "\n\tTotal: %zu Vertices, %zu Edges, %zu Subnets\n\n",
2417 vertices_count(&ted
->vertices
),
2418 edges_count(&ted
->edges
), subnets_count(&ted
->subnets
));
2422 void ls_dump_ted(struct ls_ted
*ted
)
2424 struct ls_vertex
*vertex
;
2425 struct ls_edge
*edge
;
2426 struct ls_subnet
*subnet
;
2427 const struct in_addr inaddr_any
= {.s_addr
= INADDR_ANY
};
2429 zlog_debug("(%s) Ted init", __func__
);
2431 /* Loop TED, start printing Node, then Attributes and finally Prefix */
2432 frr_each (vertices
, &ted
->vertices
, vertex
) {
2433 zlog_debug(" Ted node (%s %pI4 %s)",
2434 vertex
->node
->name
[0] ? vertex
->node
->name
2436 &vertex
->node
->router_id
,
2437 origin2txt
[vertex
->node
->adv
.origin
]);
2438 struct listnode
*lst_node
;
2439 struct ls_edge
*vertex_edge
;
2441 for (ALL_LIST_ELEMENTS_RO(vertex
->incoming_edges
, lst_node
,
2444 " inc edge key:%" PRIu64
" attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2446 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2447 &vertex_edge
->attributes
->standard
.local
,
2448 &vertex_edge
->attributes
->standard
.remote
);
2450 for (ALL_LIST_ELEMENTS_RO(vertex
->outgoing_edges
, lst_node
,
2453 " out edge key:%" PRIu64
" attr key:%pI4 loc:(%pI4) rmt:(%pI4)",
2455 &vertex_edge
->attributes
->adv
.id
.ip
.addr
,
2456 &vertex_edge
->attributes
->standard
.local
,
2457 &vertex_edge
->attributes
->standard
.remote
);
2460 frr_each (edges
, &ted
->edges
, edge
) {
2461 zlog_debug(" Ted edge key:%" PRIu64
"src:%pI4 dst:%pI4", edge
->key
,
2462 edge
->source
? &edge
->source
->node
->router_id
2465 ? &edge
->destination
->node
->router_id
2468 frr_each (subnets
, &ted
->subnets
, subnet
) {
2469 zlog_debug(" Ted subnet key:%pFX vertex:%pI4",
2470 &subnet
->ls_pref
->pref
,
2471 &subnet
->vertex
->node
->adv
.id
.ip
.addr
);
2473 zlog_debug("(%s) Ted end", __func__
);